| 1 | /** Transport-independent input and scoped, opaque push transactions. */ |
| 2 | import * as Effect from "effect/Effect"; |
| 3 | import type * as Fiber from "effect/Fiber"; |
| 4 | import type * as Result from "effect/Result"; |
| 5 | import type { RuntimeContext } from "../RuntimeContext.ts"; |
| 6 | import type { ObjectType } from "./Protocol/ObjectCodec.ts"; |
| 7 | import { StoreError } from "./Protocol/Store.ts"; |
| 8 | import type { |
| 9 | CommitPushResult, |
| 10 | RefCommand, |
| 11 | RepoMetaData, |
| 12 | } from "./RepoObject.ts"; |
| 13 | import type { StreamingFeeder } from "./Store/StreamingSource.ts"; |
| 14 | |
| 15 | /** A proposed ref change. Zero old/new OIDs mean creation/deletion. */ |
| 16 | export type RefUpdate = RefCommand; |
| 17 | |
| 18 | /** Decoded commands and a streaming pack. Use the HTTP decoder or Push.fromStream to construct inputs. */ |
| 19 | export interface PushInput { |
| 20 | readonly updates: ReadonlyArray<RefUpdate>; |
| 21 | readonly atomic: boolean; |
| 22 | } |
| 23 | |
| 24 | /** @internal The decoder and engine share this state; applications see PushInput. */ |
| 25 | export interface IncomingState { |
| 26 | readonly feeder: StreamingFeeder; |
| 27 | readonly receiving: Fiber.Fiber< |
| 28 | Result.Result<{ readonly total: number }, StoreError> |
| 29 | >; |
| 30 | readonly packStart: number; |
| 31 | readonly declaredBytes: number | undefined; |
| 32 | active: boolean; |
| 33 | claimed: boolean; |
| 34 | } |
| 35 | |
| 36 | /** @internal */ |
| 37 | export const incomingStates = new WeakMap<PushInput, IncomingState>(); |
| 38 | |
| 39 | /** A staged push, usable only within the scope that prepared it. */ |
| 40 | export interface PreparedPush { |
| 41 | readonly repo: RepoMetaData; |
| 42 | readonly updates: ReadonlyArray<RefUpdate>; |
| 43 | /** Read an incoming or existing object, bounded to 1 MiB by default. */ |
| 44 | readonly readObject: ( |
| 45 | oid: string, |
| 46 | maxBytes?: number, |
| 47 | ) => Effect.Effect< |
| 48 | { readonly type: ObjectType; readonly content: Uint8Array } | undefined, |
| 49 | StoreError, |
| 50 | RuntimeContext |
| 51 | >; |
| 52 | } |
| 53 | |
| 54 | /** @internal */ |
| 55 | export const preparedStates = new WeakMap< |
| 56 | PreparedPush, |
| 57 | { |
| 58 | readonly owner: object; |
| 59 | readonly commit: Effect.Effect< |
| 60 | CommitPushResult, |
| 61 | StoreError, |
| 62 | RuntimeContext |
| 63 | >; |
| 64 | } |
| 65 | >(); |
| 66 | |
| 67 | /** A transaction/input was already consumed, escaped its scope, or belongs to another engine. */ |
| 68 | export const invalidPush = () => |
| 69 | new StoreError({ |
| 70 | reason: "push is no longer active or belongs to another engine", |
| 71 | }); |