# PostgresEventStore

Durable storage on PostgreSQL, through any `effect/sql` PostgreSQL driver.

A sequence can’t number events here. Transactions commit in a different order from the one they drew their numbers in, so a view model that has read up to 6 would never come back for a 5 that commits later. Positions come from a counter row instead, which an append holds until it commits: writers wait for each other at that one step, and positions follow commit order with no gaps.

Because of that row, appends from one process are written in groups: those that arrive while a group is being written go together into the next one, a single statement that checks each stream’s version, takes positions for the appends that pass and inserts their events. An append that fails its check fails alone.

An append inside a transaction of the caller’s is written there and then, and holds the counter row until that transaction ends: every other writer of the store waits for it meanwhile, so such transactions should be short.

The statement also sends a notification with the new head on a channel named after the events table. A store on a `PgClient` listens to it, so view models in every process wake up on every append.

## Interfaces

### Options

Defined in: [src/PostgresEventStore.ts:42](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L42)

#### Properties

##### checkpointsTable?

> `readonly` `optional` **checkpointsTable?**: `string`

Defined in: [src/PostgresEventStore.ts:44](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L44)

##### eventsTable?

> `readonly` `optional` **eventsTable?**: `string`

Defined in: [src/PostgresEventStore.ts:43](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L43)

##### listen?

> `readonly` `optional` **listen?**: `boolean`

Defined in: [src/PostgresEventStore.ts:57](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L57)

Listens for appends from other processes when the `SqlClient` is a `PgClient` from `@effect/sql-pg`. Listening holds a connection. Defaults to `true`. Turn it off behind a pooler that doesn’t keep sessions, such as PgBouncer in transaction mode, and set `pollInterval` instead.

##### migrate?

> `readonly` `optional` **migrate?**: `boolean`

Defined in: [src/PostgresEventStore.ts:50](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L50)

Creates the tables, or brings tables of an earlier version up to date, on startup. Defaults to `true`. Set it to `false` where the application may not change the schema, and apply [migrations](https://effect-cqrs.dambox.ch/reference/api/postgreseventstore/#migrations) with your own tooling.

##### pollInterval?

> `readonly` `optional` **pollInterval?**: `Input`

Defined in: [src/PostgresEventStore.ts:59](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L59)

Reads the head this often, see `EventStore.MakeOptions`. Off by default.

## Type Aliases

### Migration

> **Migration** = [`Migration`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#migration)

Defined in: [src/PostgresEventStore.ts:63](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L63)

A schema change, see `EventStore.Migration`. Migrations are listed in the order to apply them.

## Variables

### make

> `const` **make**: (…`args`) => `Effect`<{ `afterCommit?`: <`R`>(`effect`) => `Effect`<`void`, `never`, `R`>; `changes`: `Stream`<`number`>; `head`: `Effect`<`number`, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror)>; `append`(`input`): `Effect`\<readonly `object`\[], [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror) | [`ConcurrencyConflict`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#concurrencyconflict)>; `read`(`filter?`): `Stream`<{ `aggregateId`: `string`; `aggregateName`: `string`; `causationId`: `string` | `null`; `correlationId`: `string` | `null`; `metadata`: {\[`key`: `string`]: `Json`; }; `payload`: `Json`; `position`: `number`; `schemaVersion`: `number`; `timestamp`: `Utc`; `type`: `string`; `version`: `number`; }, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror)>; `subscribe`(`filter?`): `Stream`<{ `aggregateId`: `string`; `aggregateName`: `string`; `causationId`: `string` | `null`; `correlationId`: `string` | `null`; `metadata`: {\[`key`: `string`]: `Json`; }; `payload`: `Json`; `position`: `number`; `schemaVersion`: `number`; `timestamp`: `Utc`; `type`: `string`; `version`: `number`; }, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror)>; }, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror), `Scope` | `SqlClient`>

Defined in: [src/PostgresEventStore.ts:222](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L222)

#### Parameters

##### args

…\[`options?`: [`Options`](https://effect-cqrs.dambox.ch/reference/api/postgreseventstore/#options)]

#### Returns

`Effect`<{ `afterCommit?`: <`R`>(`effect`) => `Effect`<`void`, `never`, `R`>; `changes`: `Stream`<`number`>; `head`: `Effect`<`number`, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror)>; `append`(`input`): `Effect`\<readonly `object`\[], [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror) | [`ConcurrencyConflict`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#concurrencyconflict)>; `read`(`filter?`): `Stream`<{ `aggregateId`: `string`; `aggregateName`: `string`; `causationId`: `string` | `null`; `correlationId`: `string` | `null`; `metadata`: {\[`key`: `string`]: `Json`; }; `payload`: `Json`; `position`: `number`; `schemaVersion`: `number`; `timestamp`: `Utc`; `type`: `string`; `version`: `number`; }, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror)>; `subscribe`(`filter?`): `Stream`<{ `aggregateId`: `string`; `aggregateName`: `string`; `causationId`: `string` | `null`; `correlationId`: `string` | `null`; `metadata`: {\[`key`: `string`]: `Json`; }; `payload`: `Json`; `position`: `number`; `schemaVersion`: `number`; `timestamp`: `Utc`; `type`: `string`; `version`: `number`; }, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror)>; }, [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror), `Scope` | `SqlClient`>

## Functions

### layer()

> **layer**(`options?`): `Layer`<[`EventStore`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstore), [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror), `SqlClient`>

Defined in: [src/PostgresEventStore.ts:408](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L408)

#### Parameters

##### options?

[`Options`](https://effect-cqrs.dambox.ch/reference/api/postgreseventstore/#options)

#### Returns

`Layer`<[`EventStore`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstore), [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror), `SqlClient`>

***

### layerCheckpoints()

> **layerCheckpoints**(`options?`): `Layer`<[`Checkpoints`](https://effect-cqrs.dambox.ch/reference/api/checkpoints/#checkpoints), [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror), `SqlClient`>

Defined in: [src/PostgresEventStore.ts:414](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L414)

Keeps checkpoints in the same database, for view models that are durable too.

#### Parameters

##### options?

[`Options`](https://effect-cqrs.dambox.ch/reference/api/postgreseventstore/#options)

#### Returns

`Layer`<[`Checkpoints`](https://effect-cqrs.dambox.ch/reference/api/checkpoints/#checkpoints), [`EventStoreError`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#eventstoreerror), `SqlClient`>

***

### migrations()

> **migrations**(`options?`): readonly [`Migration`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#migration)\[]

Defined in: [src/PostgresEventStore.ts:142](https://github.com/davidnussio/effect-cqrs/blob/9d66af7141782f3f89655e6868abe3f141c97632/src/PostgresEventStore.ts#L142)

The schema of the events and checkpoints tables, for tools that apply migrations themselves. `layer` and `layerCheckpoints` run the same statements on startup unless `migrate` is `false`.

#### Parameters

##### options?

[`Options`](https://effect-cqrs.dambox.ch/reference/api/postgreseventstore/#options)

#### Returns

readonly [`Migration`](https://effect-cqrs.dambox.ch/reference/api/eventstore/#migration)\[]
