StoredWorkflowOutboxEntry.java

package org.hammer.audio.workflow.collaboration.store;

import java.time.Instant;
import java.util.Objects;

/**
 * Immutable durable collaboration outbox entry.
 *
 * @param eventId stable idempotency identifier for the event
 * @param sessionId owning collaboration-session identifier
 * @param sequence durable session event sequence
 * @param revision semantic revision associated with the event
 * @param eventType stable collaboration event type
 * @param occurredAt event occurrence timestamp
 * @param payload deterministic serialized event payload
 * @param attemptCount number of completed publication attempts
 * @param nextAttemptAt earliest timestamp for the next publication attempt
 * @param publishedAt successful publication timestamp, or {@code null} while pending
 */
public record StoredWorkflowOutboxEntry(
    String eventId,
    String sessionId,
    long sequence,
    long revision,
    String eventType,
    Instant occurredAt,
    String payload,
    int attemptCount,
    Instant nextAttemptAt,
    Instant publishedAt) {

  public StoredWorkflowOutboxEntry {
    eventId = requireNotBlank(eventId, "eventId");
    sessionId = requireNotBlank(sessionId, "sessionId");
    requirePositive(sequence, "sequence");
    requirePositive(revision, "revision");
    eventType = requireNotBlank(eventType, "eventType");
    Objects.requireNonNull(occurredAt, "occurredAt");
    payload = requireNotBlank(payload, "payload");
    if (attemptCount < 0) {
      throw new IllegalArgumentException("attemptCount must be >= 0");
    }
    Objects.requireNonNull(nextAttemptAt, "nextAttemptAt");
  }

  /** Returns whether the event still awaits successful publication. */
  public boolean pending() {
    return publishedAt == null;
  }

  private static String requireNotBlank(String value, String name) {
    Objects.requireNonNull(value, name);
    if (value.isBlank()) {
      throw new IllegalArgumentException(name + " must not be blank");
    }
    return value;
  }

  private static void requirePositive(long value, String name) {
    if (value <= 0) {
      throw new IllegalArgumentException(name + " must be > 0");
    }
  }
}