Tx
The transaction of one Session commit, available as a service inside Session.commit(body).
Everything a body stages is written in one atomic storage batch, or not at all. Table reads are allowed only before
the transaction’s first table write (ReadAfterWrite); document access is not a table read.
import { Session, type State, Tx } from "@effective-harness/core"import * as Effect from "effect/Effect"
declare const Todos: State.ConversationDefinition<{ readonly items: ReadonlyArray<string> }>
const program = Session.commit( Effect.gen(function* () { const conversation = yield* Tx.createConversation({ ownership: { kind: "ownerless" } }) yield* Tx.appendEntry(conversation.id, { kind: "app.note", data: "hello" }) yield* Tx.update(Todos.of(conversation.id), (todos) => ({ items: [...todos.items, "write docs"] })) }))Since v0.0.0
ReadError (type alias)
Section titled “ReadError (type alias)”Failures of table reads.
Signature
type ReadError = StorageFailure | ReadAfterWrite | TransactionSettledSince v0.0.0
TaskOptions (interface)
Section titled “TaskOptions (interface)”Where a new task lives and whether the scheduler treats it as a boundary.
Signature
export interface TaskOptions { readonly ownership: TaskOwnership /** Excluded from idle waits, conversation aborts and cascades. Conversation-owned tasks only. */ readonly background?: boolean}Since v0.0.0
Tx (class)
Section titled “Tx (class)”Signature
declare class TxSince v0.0.0
TxShape (interface)
Section titled “TxShape (interface)”Signature
export interface TxShape { // Table reads readonly conversation: (id: ConversationId) => Effect.Effect<Option.Option<ConversationRecord>, ReadError> readonly entry: (id: EntryId) => Effect.Effect<Option.Option<EntryRecord>, ReadError> readonly task: (id: TaskId) => Effect.Effect<Option.Option<TaskRecord>, ReadError> readonly scanConversations: ( query: ConversationQuery, limit: number, cursor?: Cursor ) => Effect.Effect<Page<ConversationRecord>, ReadError> readonly scanEntries: ( query: EntryQuery, limit: number, cursor?: Cursor ) => Effect.Effect<Page<EntryRecord>, ReadError> readonly latestHeadMarker: ( conversationId: ConversationId ) => Effect.Effect<Option.Option<EntryRecord & { readonly head: EntryId }>, ReadError> readonly scanTasks: (query: TaskQuery, limit: number, cursor?: Cursor) => Effect.Effect<Page<TaskRecord>, ReadError> readonly submission: (id: SubmissionId) => Effect.Effect<Option.Option<SubmissionRecord>, ReadError> /** The submission with a conversation-scoped request ID. */ readonly submissionByRequest: ( conversationId: ConversationId, requestId: string ) => Effect.Effect<Option.Option<SubmissionRecord>, ReadError>
// Table writes readonly createConversation: (options: { readonly ownership: ConversationOwnership }) => Effect.Effect<ConversationRecord, WriteError> /** * Create a conversation that continues from one visible entry of another. It sees the parent's transcript through * that entry; each conversation state follows its fork policy (`asOf`: the value at the entry's commit, `current`: * the committed value now, `initial`: not copied). Task state and tasks are never copied. */ readonly forkConversation: ( parentConversationId: ConversationId, at: EntryId, options: { readonly ownership: ConversationOwnership } ) => Effect.Effect<ConversationRecord, WriteError> readonly appendEntry: (conversationId: ConversationId, draft: EntryDraft) => Effect.Effect<EntryRecord, WriteError> /** Create a raw submission record; no admission rules apply. Hosts use `Conversation.submit`. */ readonly createSubmission: (create: SubmissionCreate) => Effect.Effect<SubmissionRecord, WriteError> /** * Settle a queued or placed submission; only a placed input can be answered. A settled one stays unchanged. Resolved * at assembly against the transaction's latest candidate, so it is not a table read. */ readonly settleSubmission: ( id: SubmissionId, settlement: SubmissionSettlement ) => Effect.Effect<void, TransactionSettled> /** Record a queued submission's placement at `entry`: an input becomes `placed`, a write `done`. */ readonly placeSubmission: (id: SubmissionId, entry: EntryId) => Effect.Effect<void, TransactionSettled> /** * Create a pending task. A child task lives in its owner's conversation. New owned work needs a live owner in the * commit's final state: not `completing`, terminal or abort-marked. */ readonly createTask: <I, C extends Task.Checkpoint, R>( task: Task.Task<I, C, R>, input: I, options: TaskOptions ) => Effect.Effect<TaskId, WriteError>
// Documents readonly doc: <A>(ref: State.Ref<A>) => Effect.Effect<A, WriteError> readonly update: <A>(ref: State.Ref<A>, f: (value: A) => A) => Effect.Effect<A, WriteError> readonly set: <A>(ref: State.Ref<A>, value: A) => Effect.Effect<void, WriteError> readonly retire: <A>(ref: State.Ref<A>) => Effect.Effect<void, WriteError>}Since v0.0.0
WriteError (type alias)
Section titled “WriteError (type alias)”Failures of staging writes.
Signature
type WriteError = | StorageFailure | TransactionSettled | ConversationNotFound | EntryNotVisible | TaskNotFound | OwnerNotLive | TaskRejected | StateErrorSince v0.0.0
appendEntry
Section titled “appendEntry”Append an immutable entry.
Signature
declare const appendEntry: (conversationId: ConversationId, draft: EntryDraft) => anySince v0.0.0
conversation
Section titled “conversation”Signature
declare const conversation: (id: ConversationId) => anySince v0.0.0
createConversation
Section titled “createConversation”Create a conversation with explicitly selected ownership.
Signature
declare const createConversation: (options: { readonly ownership: ConversationOwnership }) => anySince v0.0.0
createSubmission
Section titled “createSubmission”Signature
declare const createSubmission: (create: SubmissionCreate) => anySince v0.0.0
createTask
Section titled “createTask”Create a pending task; see TxShape.createTask.
Signature
declare const createTask: <I, C extends Task.Checkpoint, R>( task: Task.Task<I, C, R>, input: I, options: TaskOptions) => anySince v0.0.0
The staged value, creating the document with its initial value when absent.
Signature
declare const doc: <A>(ref: State.Ref<A>) => anySince v0.0.0
Signature
declare const entry: (id: EntryId) => anySince v0.0.0
forkConversation
Section titled “forkConversation”Fork a conversation at one visible entry; see TxShape.forkConversation.
Signature
declare const forkConversation: ( parentConversationId: ConversationId, at: EntryId, options: { readonly ownership: ConversationOwnership }) => anySince v0.0.0
latestHeadMarker
Section titled “latestHeadMarker”The newest visible entry of the conversation that carries a head.
Signature
declare const latestHeadMarker: (conversationId: ConversationId) => anySince v0.0.0
placeSubmission
Section titled “placeSubmission”Signature
declare const placeSubmission: (id: SubmissionId, entry: EntryId) => anySince v0.0.0
retire
Section titled “retire”Retire the current incarnation; a later access in the same transaction creates a new one.
Signature
declare const retire: <A>(ref: State.Ref<A>) => anySince v0.0.0
scanConversations
Section titled “scanConversations”Signature
declare const scanConversations: (query: ConversationQuery, limit: number, cursor?: Cursor) => anySince v0.0.0
scanEntries
Section titled “scanEntries”Newest-first.
Signature
declare const scanEntries: (query: EntryQuery, limit: number, cursor?: Cursor) => anySince v0.0.0
scanTasks
Section titled “scanTasks”Signature
declare const scanTasks: (query: TaskQuery, limit: number, cursor?: Cursor) => anySince v0.0.0
Replace the staged value, creating the document when absent.
Signature
declare const set: <A>(ref: State.Ref<A>, value: A) => anySince v0.0.0
settleSubmission
Section titled “settleSubmission”Signature
declare const settleSubmission: (id: SubmissionId, settlement: SubmissionSettlement) => anySince v0.0.0
submission
Section titled “submission”Signature
declare const submission: (id: SubmissionId) => anySince v0.0.0
submissionByRequest
Section titled “submissionByRequest”Signature
declare const submissionByRequest: (conversationId: ConversationId, requestId: string) => anySince v0.0.0
Signature
declare const task: (id: TaskId) => anySince v0.0.0
update
Section titled “update”Replace the staged value with f(value), creating the document when absent; returns the new value.
Signature
declare const update: <A>(ref: State.Ref<A>, f: (value: A) => A) => anySince v0.0.0