@useairfoil/connector-kit 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE.txt +201 -0
  2. package/METRICS.md +27 -30
  3. package/README.md +33 -51
  4. package/dist/{annotations-BE74YmAO.d.mts → annotations-vzSzXtr-.d.mts} +5 -10
  5. package/dist/{wings-I56hGtNv.mjs → arrow-flight-DDQ0ktx9.mjs} +25 -99
  6. package/dist/arrow-flight-DDQ0ktx9.mjs.map +1 -0
  7. package/dist/connector-app/index.d.mts +2 -2
  8. package/dist/connector-app/index.mjs +2 -2
  9. package/dist/connector-app-C6_dZnhE.mjs +256 -0
  10. package/dist/connector-app-C6_dZnhE.mjs.map +1 -0
  11. package/dist/{constants-D-GQzpHZ.mjs → constants-v3UX-hf6.mjs} +3 -2
  12. package/dist/constants-v3UX-hf6.mjs.map +1 -0
  13. package/dist/demo/index.d.mts +1 -1
  14. package/dist/demo/index.mjs +1 -1
  15. package/dist/{demo-B30Vlkk2.mjs → demo-DqTJ7TWI.mjs} +32 -19
  16. package/dist/demo-DqTJ7TWI.mjs.map +1 -0
  17. package/dist/iceberg/index.d.mts +3 -3
  18. package/dist/iceberg/index.mjs +3 -3
  19. package/dist/iceberg-Cj2PwlNm.mjs +30 -0
  20. package/dist/iceberg-Cj2PwlNm.mjs.map +1 -0
  21. package/dist/{index-DJhDp4Xc.d.mts → index-BTAbexBp.d.mts} +13 -16
  22. package/dist/{index-BUHSGm9Q.d.mts → index-Byr8NTdG.d.mts} +2 -2
  23. package/dist/{index-Dk7urvpF.d.mts → index-CV6V6fyx.d.mts} +9 -6
  24. package/dist/{index-NnCutIqM.d.mts → index-CZKx2Yce.d.mts} +29 -19
  25. package/dist/{index-BfXpgxk9.d.mts → index-DeTwIUKl.d.mts} +3 -3
  26. package/dist/{index-CRVAwJ5-.d.mts → index-dHS59EZl.d.mts} +4 -4
  27. package/dist/{index-ygpml2kC.d.mts → index-fHIJJoRe.d.mts} +17 -10
  28. package/dist/index-uFa2wwYo.d.mts +27 -0
  29. package/dist/index.d.mts +11 -11
  30. package/dist/index.mjs +10 -10
  31. package/dist/ingestion/index.d.mts +1 -1
  32. package/dist/ingestion/index.mjs +1 -1
  33. package/dist/{ingestion-q0WwqUSt.mjs → ingestion-DoCUwm5N.mjs} +6 -6
  34. package/dist/{ingestion-q0WwqUSt.mjs.map → ingestion-DoCUwm5N.mjs.map} +1 -1
  35. package/dist/ingestor/index.d.mts +3 -3
  36. package/dist/ingestor/index.mjs +3 -3
  37. package/dist/{ingestor-D4L-HPkg.mjs → ingestor-DjCEzBzZ.mjs} +6 -6
  38. package/dist/ingestor-DjCEzBzZ.mjs.map +1 -0
  39. package/dist/{instrumented-Bhp7fyvh.mjs → instrumented-Bq1WX2L5.mjs} +2 -2
  40. package/dist/{instrumented-Bhp7fyvh.mjs.map → instrumented-Bq1WX2L5.mjs.map} +1 -1
  41. package/dist/manifest/index.mjs +1 -1
  42. package/dist/{manifest-BGKxmKLy.mjs → manifest-CABeIhAG.mjs} +2 -2
  43. package/dist/{manifest-BGKxmKLy.mjs.map → manifest-CABeIhAG.mjs.map} +1 -1
  44. package/dist/{metrics-BaEX__MN.mjs → metrics-C901IIYZ.mjs} +6 -11
  45. package/dist/metrics-C901IIYZ.mjs.map +1 -0
  46. package/dist/{metrics-CVXFL7YT.d.mts → metrics-DoJ0WeKu.d.mts} +2 -2
  47. package/dist/metrics.d.mts +1 -1
  48. package/dist/metrics.mjs +1 -1
  49. package/dist/runtime-config/index.d.mts +2 -2
  50. package/dist/runtime-config/index.mjs +3 -3
  51. package/dist/{runtime-config-Oa55gAew.mjs → runtime-config-Bn8Fivt1.mjs} +11 -8
  52. package/dist/runtime-config-Bn8Fivt1.mjs.map +1 -0
  53. package/dist/{server-CMnxz3h0.mjs → server-D1TTN0_D.mjs} +3 -3
  54. package/dist/{server-CMnxz3h0.mjs.map → server-D1TTN0_D.mjs.map} +1 -1
  55. package/dist/{service-DLkhuxYl.d.mts → service-BRoy_EId.d.mts} +2 -2
  56. package/dist/state-store/index.mjs +1 -1
  57. package/dist/{state-store-uFvHY7Ax.mjs → state-store-DhSrKVEH.mjs} +2 -2
  58. package/dist/{state-store-uFvHY7Ax.mjs.map → state-store-DhSrKVEH.mjs.map} +1 -1
  59. package/dist/status/index.d.mts +1 -1
  60. package/dist/status/index.mjs +1 -1
  61. package/dist/{status-CKb9IhQ9.mjs → status-4h6Oxh-O.mjs} +2 -2
  62. package/dist/{status-CKb9IhQ9.mjs.map → status-4h6Oxh-O.mjs.map} +1 -1
  63. package/dist/{table-V0tgUC5i.mjs → table-CxM09xf7.mjs} +22 -85
  64. package/dist/table-CxM09xf7.mjs.map +1 -0
  65. package/dist/{types-xZtSmrGA.d.mts → types-NtSv6gwl.d.mts} +3 -3
  66. package/dist/webhook/index.d.mts +2 -2
  67. package/dist/webhook/index.mjs +1 -1
  68. package/package.json +19 -18
  69. package/src/catalog/retry.ts +25 -0
  70. package/src/catalog/table.ts +73 -37
  71. package/src/connector-app/create-table.ts +8 -8
  72. package/src/connector-app/demo.ts +24 -19
  73. package/src/connector-app/index.ts +1 -0
  74. package/src/connector-app/setup.ts +69 -0
  75. package/src/core/types.ts +1 -1
  76. package/src/demo/definition.ts +1 -1
  77. package/src/demo/generate.ts +1 -1
  78. package/src/demo/run.ts +60 -30
  79. package/src/iceberg/annotations.ts +3 -16
  80. package/src/iceberg/index.ts +2 -2
  81. package/src/iceberg/table.ts +28 -78
  82. package/src/ingestion/engine.ts +1 -1
  83. package/src/ingestor/{wings.ts → arrow-flight.ts} +25 -27
  84. package/src/ingestor/console.ts +1 -1
  85. package/src/ingestor/index.ts +5 -1
  86. package/src/runtime-config/config.ts +8 -3
  87. package/src/runtime-config/constants.ts +2 -1
  88. package/src/runtime-config/index.ts +1 -1
  89. package/src/runtime-config/table-bindings.ts +6 -4
  90. package/src/telemetry.ts +11 -19
  91. package/dist/connector-app-C-L4QqG6.mjs +0 -123
  92. package/dist/connector-app-C-L4QqG6.mjs.map +0 -1
  93. package/dist/constants-D-GQzpHZ.mjs.map +0 -1
  94. package/dist/demo-B30Vlkk2.mjs.map +0 -1
  95. package/dist/iceberg-D6L8I6vA.mjs +0 -39
  96. package/dist/iceberg-D6L8I6vA.mjs.map +0 -1
  97. package/dist/index-CUPP2A_m.d.mts +0 -27
  98. package/dist/ingestor-D4L-HPkg.mjs.map +0 -1
  99. package/dist/metrics-BaEX__MN.mjs.map +0 -1
  100. package/dist/runtime-config-Oa55gAew.mjs.map +0 -1
  101. package/dist/table-V0tgUC5i.mjs.map +0 -1
  102. package/dist/wings-I56hGtNv.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iceberg-Cj2PwlNm.mjs","names":[],"sources":["../src/iceberg/annotations.ts","../src/iceberg/index.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\ndeclare module \"effect/Schema\" {\n namespace Annotations {\n interface Annotations {\n readonly icebergIdentifierFields?: ReadonlyArray<string> | undefined;\n }\n }\n}\n\ntype KnownField<S extends Schema.Top> = keyof S[\"Type\"] & string;\n\n/** A row field that cannot be null or undefined. */\nexport type RequiredField<S extends Schema.Top> = [KnownField<S>] extends [never]\n ? string\n : {\n readonly [Field in KnownField<S>]-?: undefined extends S[\"Type\"][Field]\n ? never\n : null extends S[\"Type\"][Field]\n ? never\n : Field;\n }[KnownField<S>];\n\n/** A row schema whose identifier fields are `Key`. Only the type has it. */\nexport interface Identified<Key extends string> {\n readonly \"~iceberg.identifier\": Key;\n}\n\n/**\n * Marks the fields that identify a row. The engine upserts rows by them.\n *\n * Put it last. A later `.annotate()` keeps the runtime annotation, but the type\n * loses the key, so `Resource.entity` stops compiling.\n *\n * @example\n * ```ts\n * const Post = Schema.Struct({\n * id: Schema.String,\n * updatedAt: Schema.String,\n * }).pipe(Iceberg.identifier(\"id\"));\n * ```\n */\nexport const identifier =\n <S extends Schema.Top, const Key extends RequiredField<S>>(\n ...keys: readonly [Key, ...ReadonlyArray<Key>]\n ) =>\n (schema: S): S[\"Rebuild\"] & Identified<Key> =>\n // Effect has no slot for the key in the schema type, so we add it.\n schema.annotate({ icebergIdentifierFields: keys }) as S[\"Rebuild\"] & Identified<Key>;\n","export { identifier } from \"./annotations\";\nexport { IcebergSchemaError } from \"./error\";\nexport { makeCreateTableRequest, type CreateTableOptions } from \"./table\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0CA,MAAa,cAET,GAAG,UAEJ,WAEC,OAAO,SAAS,EAAE,yBAAyB,KAAK,CAAC"}
@@ -1,6 +1,6 @@
1
- import { a as ids, i as identifier, r as field } from "./annotations-BE74YmAO.mjs";
1
+ import { r as identifier } from "./annotations-vzSzXtr-.mjs";
2
2
  import { Effect, Schema } from "effect";
3
- import { CommitTableRequest } from "iceberg-js";
3
+ import { CreateTableRequest } from "iceberg-js";
4
4
  //#region src/iceberg/error.d.ts
5
5
  declare const IcebergSchemaError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
6
6
  readonly _tag: "IcebergSchemaError";
@@ -15,20 +15,16 @@ declare class IcebergSchemaError extends IcebergSchemaError_base<{
15
15
  //#endregion
16
16
  //#region src/iceberg/table.d.ts
17
17
  /** Options for creating a table. */
18
- type CreateTableCommitOptions = {
18
+ type CreateTableOptions = {
19
+ readonly name: string;
19
20
  /** Where the table's files go. The catalog may choose this when omitted. */
20
21
  readonly location?: string | undefined;
21
- /** UUID for the table. Random by default. */
22
- readonly uuid?: string | undefined;
23
22
  /** Extra table properties. These win over the ones from the schema. */
24
23
  readonly properties?: Readonly<Record<string, string>> | undefined;
25
24
  };
26
25
  /**
27
- * Builds the commit that creates an Iceberg table from an Effect schema.
28
- *
29
- * The field IDs come from the schema, so the table has to keep them. Send the
30
- * commit with `commitTable`. Then load the table and check the IDs before you
31
- * write any rows. Don't use `createTable` here, because it can change the IDs.
26
+ * Builds a REST create-table request from an Effect schema.
27
+ * The catalog assigns the stored field IDs.
32
28
  *
33
29
  * A root `description` becomes the table `comment`, and a field `description`
34
30
  * becomes its `doc`. `title` and `examples` are dropped.
@@ -39,20 +35,21 @@ type CreateTableCommitOptions = {
39
35
  * @example
40
36
  * ```ts
41
37
  * const Row = Schema.Struct({
42
- * id: Schema.String.pipe(Iceberg.field(1, { description: "Stable row identifier" })),
38
+ * id: Schema.String.pipe(Schema.annotateKey({ description: "Row identifier" })),
43
39
  * })
44
40
  * .annotate({ description: "Connector rows" })
45
41
  * .pipe(Iceberg.identifier("id"))
46
42
  *
47
- * const request = yield* Iceberg.makeCreateTableCommitRequest(Row, {
43
+ * const request = yield* Iceberg.makeCreateTableRequest(Row, {
44
+ * name: "rows",
48
45
  * location: "s3://warehouse/rows"
49
46
  * })
50
47
  * ```
51
48
  */
52
- declare const makeCreateTableCommitRequest: (schema: Schema.Top, options: CreateTableCommitOptions) => Effect.Effect<CommitTableRequest, IcebergSchemaError>;
49
+ declare const makeCreateTableRequest: (schema: Schema.Top, options: CreateTableOptions) => Effect.Effect<CreateTableRequest, IcebergSchemaError>;
53
50
  declare namespace index_d_exports {
54
- export { CreateTableCommitOptions, IcebergSchemaError, field, identifier, ids, makeCreateTableCommitRequest };
51
+ export { CreateTableOptions, IcebergSchemaError, identifier, makeCreateTableRequest };
55
52
  }
56
53
  //#endregion
57
- export { IcebergSchemaError as i, CreateTableCommitOptions as n, makeCreateTableCommitRequest as r, index_d_exports as t };
58
- //# sourceMappingURL=index-DJhDp4Xc.d.mts.map
54
+ export { IcebergSchemaError as i, CreateTableOptions as n, makeCreateTableRequest as r, index_d_exports as t };
55
+ //# sourceMappingURL=index-BTAbexBp.d.mts.map
@@ -1,4 +1,4 @@
1
- import { r as ConnectorDefinition } from "./types-xZtSmrGA.mjs";
1
+ import { r as ConnectorDefinition } from "./types-NtSv6gwl.mjs";
2
2
  import { i as StateStore } from "./index-CgvFomO6.mjs";
3
3
  import { Schema } from "effect";
4
4
  import { HttpRouter } from "effect/http";
@@ -75,4 +75,4 @@ declare namespace index_d_exports {
75
75
  }
76
76
  //#endregion
77
77
  export { ResourceStatusSchema as a, StatusUnavailableResponse as c, SyncStateSchema as d, statusRoute as f, ResourceStatus as i, StatusUnavailableResponseSchema as l, ResourceError as n, StatusResponse as o, ResourceErrorSchema as r, StatusResponseSchema as s, index_d_exports as t, SyncState as u };
78
- //# sourceMappingURL=index-BUHSGm9Q.d.mts.map
78
+ //# sourceMappingURL=index-Byr8NTdG.d.mts.map
@@ -1,10 +1,10 @@
1
1
  import { t as ConnectorError } from "./index-DkVNO6ks.mjs";
2
- import { _ as ResourceRequiredField, b as ResourceSchema } from "./types-xZtSmrGA.mjs";
3
- import { i as Ingestor, n as IngestResult } from "./service-DLkhuxYl.mjs";
2
+ import { _ as ResourceRequiredField, b as ResourceSchema } from "./types-NtSv6gwl.mjs";
3
+ import { i as Ingestor, n as IngestResult } from "./service-BRoy_EId.mjs";
4
4
  import { Effect, Schema } from "effect";
5
5
  import { Faker } from "@faker-js/faker";
6
6
  //#region src/demo/generate.d.ts
7
- /** What one run shares: the seeded Faker and the time the run started. */
7
+ /** What one run shares: the Faker and the time the run started. */
8
8
  type DemoContext = {
9
9
  readonly faker: Faker;
10
10
  readonly now: Date;
@@ -36,7 +36,7 @@ type DemoDefinition<Setup extends ReadonlyArray<DemoTable> = ReadonlyArray<DemoT
36
36
  readonly tables: Group;
37
37
  readonly rows: (index: number, context: DemoContext) => DemoRows<Group>;
38
38
  /**
39
- * Groups written per chunk, 100 by default. A run can go over the size by
39
+ * Groups written per chunk, 1000 by default. A run can go over the size by
40
40
  * one chunk, so lower it when a group is big.
41
41
  */
42
42
  readonly groupsPerChunk?: number;
@@ -53,9 +53,12 @@ declare const define: <const Setup extends ReadonlyArray<DemoTable>, const Group
53
53
  type RunOptions = {
54
54
  /** Stop once this many Arrow bytes are written. */
55
55
  readonly bytes: number;
56
- readonly seed: number;
56
+ /** Omit for random data on each run. */
57
+ readonly seed?: number;
57
58
  /** The time data is made around. Same seed, time and tables give the same rows. */
58
59
  readonly now: Date;
60
+ /** Maximum rows per ingestion batch. Defaults to 500. Must be a positive integer. */
61
+ readonly batchSize?: number;
59
62
  /** Groups per chunk. Overrides the demo's. */
60
63
  readonly groupsPerChunk?: number;
61
64
  };
@@ -73,4 +76,4 @@ declare namespace index_d_exports {
73
76
  }
74
77
  //#endregion
75
78
  export { DemoDefinition as a, define as c, run as i, table as l, DemoTotals as n, DemoRows as o, RunOptions as r, DemoTable as s, index_d_exports as t, DemoContext as u };
76
- //# sourceMappingURL=index-Dk7urvpF.d.mts.map
79
+ //# sourceMappingURL=index-CV6V6fyx.d.mts.map
@@ -1,20 +1,21 @@
1
1
  import "./index-BX8G7d41.mjs";
2
2
  import { t as ConnectorError } from "./index-DkVNO6ks.mjs";
3
- import "./annotations-BE74YmAO.mjs";
4
- import { _ as ResourceRequiredField, b as ResourceSchema, d as ResourceDefinition, h as ResourceName, i as Cursor$1, l as PageFetch, n as ChangesFetch, r as ConnectorDefinition, t as ChangesFeed } from "./types-xZtSmrGA.mjs";
5
- import { a as DemoDefinition } from "./index-Dk7urvpF.mjs";
6
- import { i as Ingestor } from "./service-DLkhuxYl.mjs";
7
- import "./index-DJhDp4Xc.mjs";
3
+ import "./annotations-vzSzXtr-.mjs";
4
+ import { _ as ResourceRequiredField, b as ResourceSchema, d as ResourceDefinition, h as ResourceName, i as Cursor$1, l as PageFetch, n as ChangesFetch, r as ConnectorDefinition, t as ChangesFeed } from "./types-NtSv6gwl.mjs";
5
+ import { a as DemoDefinition } from "./index-CV6V6fyx.mjs";
6
+ import { i as Ingestor } from "./service-BRoy_EId.mjs";
7
+ import "./index-BTAbexBp.mjs";
8
8
  import { i as StateStore } from "./index-CgvFomO6.mjs";
9
- import "./index-BfXpgxk9.mjs";
10
- import "./index-CUPP2A_m.mjs";
11
- import "./index-ygpml2kC.mjs";
9
+ import "./index-DeTwIUKl.mjs";
10
+ import "./index-uFa2wwYo.mjs";
11
+ import { f as RuntimeConfigError, t as index_d_exports$1 } from "./index-fHIJJoRe.mjs";
12
12
  import "./index-eFuoMZZ3.mjs";
13
- import "./metrics-CVXFL7YT.mjs";
14
- import "./index-BUHSGm9Q.mjs";
15
- import "./index-CRVAwJ5-.mjs";
13
+ import "./metrics-DoJ0WeKu.mjs";
14
+ import "./index-Byr8NTdG.mjs";
15
+ import "./index-dHS59EZl.mjs";
16
16
  import { Config, Context, Duration, Effect, Layer, Option, Schema } from "effect";
17
17
  import { CliError, Command } from "effect/cli";
18
+ import { CatalogManager } from "@useairfoil/api";
18
19
  import { HttpRouter } from "effect/http";
19
20
  //#region src/connector-app/check.d.ts
20
21
  type ResourceCheckResult = {
@@ -153,7 +154,7 @@ declare const layerOtlp: (options?: OtlpTracingOptions & OtlpMetricsOptions) =>
153
154
  declare const layerMetricsConsoleDump: (interval?: Duration.Input) => Layer.Layer<never, never, never>;
154
155
  //#endregion
155
156
  //#region src/connector-app/create-table.d.ts
156
- /** Creates the table command for a connector's row schemas. */
157
+ /** Creates the table command; existing tables must match the connector's row schemas. */
157
158
  declare const makeCreateTableCommand: (schemas: Readonly<Record<string, Schema.Top>>) => Command.Command<"create-table", {
158
159
  readonly table: string;
159
160
  readonly catalog: string;
@@ -162,15 +163,16 @@ declare const makeCreateTableCommand: (schemas: Readonly<Record<string, Schema.T
162
163
  }, {}, ConnectorError | import("effect/Config").ConfigError | CliError.UserError, import("effect/http/HttpClient").HttpClient>;
163
164
  //#endregion
164
165
  //#region src/connector-app/demo.d.ts
165
- /** Reads sizes such as `512KiB`, `128MiB` or `1GiB`. */
166
+ /** Reads byte sizes such as `512kB`, `128MB` or `1.5GB`. */
166
167
  declare const parseSize: (input: string) => Option.Option<number>;
167
168
  /**
168
- * Creates the command that writes the demo data to Wings, then exits.
169
- * It reads Wings and table bindings from Config, so provide `RuntimeConfig.layerHosted()`.
169
+ * Creates the command that writes demo data over Arrow Flight, then exits.
170
+ * It reads hosted config and table bindings, so provide `RuntimeConfig.layerHosted()`.
170
171
  */
171
172
  declare const makeDemoCommand: (demo: DemoDefinition) => Command.Command<"demo", {
172
173
  readonly size: number;
173
- readonly seed: number;
174
+ readonly seed: Option.Option<number>;
175
+ readonly batchSize: Option.Option<number>;
174
176
  }, {}, ConnectorError, never>;
175
177
  //#endregion
176
178
  //#region src/connector-app/start.d.ts
@@ -184,9 +186,17 @@ type StartOptions = {
184
186
  readonly disableHttpLogger?: boolean;
185
187
  };
186
188
  declare const start: (app: App, options: StartOptions) => Effect.Effect<void, ConnectorError | import("effect/http/HttpServerError").ServeError, StateStore | Ingestor>;
189
+ //#endregion
190
+ //#region src/connector-app/setup.d.ts
191
+ /** Creates or verifies all bound tables without loading provider credentials. */
192
+ declare const makeSetupCommand: (schemas: Readonly<Record<string, Schema.Top>>) => Command.Command<"setup", {
193
+ readonly checkpointIntervalSec: Option.Option<number>;
194
+ readonly retryInterval: Duration.Duration;
195
+ readonly retries: number;
196
+ }, {}, ConnectorError | import("effect/Config").ConfigError | RuntimeConfigError | CatalogManager.CatalogManagerError, import("effect/http/HttpClient").HttpClient | import("effect/Scope").Scope>;
187
197
  declare namespace index_d_exports {
188
- export { App, CheckOptions, CheckResult, ResourceCheckResult, StartOptions, check, makeCreateTableCommand, makeDemoCommand, parseSize, start };
198
+ export { App, CheckOptions, CheckResult, ResourceCheckResult, StartOptions, check, makeCreateTableCommand, makeDemoCommand, makeSetupCommand, parseSize, start };
189
199
  }
190
200
  //#endregion
191
- export { makeDemoCommand as a, telemetry_d_exports as c, Fetch as d, Resource as f, check as g, ResourceCheckResult as h, start as i, Connector as l, CheckResult as m, App as n, parseSize as o, CheckOptions as p, StartOptions as r, makeCreateTableCommand as s, index_d_exports as t, Cursor as u };
192
- //# sourceMappingURL=index-NnCutIqM.d.mts.map
201
+ export { check as _, start as a, makeCreateTableCommand as c, Cursor as d, Fetch as f, ResourceCheckResult as g, CheckResult as h, StartOptions as i, telemetry_d_exports as l, CheckOptions as m, makeSetupCommand as n, makeDemoCommand as o, Resource as p, App as r, parseSize as s, index_d_exports as t, Connector as u };
202
+ //# sourceMappingURL=index-CZKx2Yce.d.mts.map
@@ -1,6 +1,6 @@
1
1
  import { t as ConnectorError } from "./index-DkVNO6ks.mjs";
2
- import { d as ResourceDefinition, i as Cursor, k as WebhookRoute, r as ConnectorDefinition } from "./types-xZtSmrGA.mjs";
3
- import { i as Ingestor } from "./service-DLkhuxYl.mjs";
2
+ import { d as ResourceDefinition, i as Cursor, k as WebhookRoute, r as ConnectorDefinition } from "./types-NtSv6gwl.mjs";
3
+ import { i as Ingestor } from "./service-BRoy_EId.mjs";
4
4
  import { i as StateStore } from "./index-CgvFomO6.mjs";
5
5
  import { Effect } from "effect";
6
6
  import { HttpRouter, HttpServer } from "effect/http";
@@ -34,4 +34,4 @@ declare namespace index_d_exports {
34
34
  }
35
35
  //#endregion
36
36
  export { RunOptions as n, run as r, index_d_exports as t };
37
- //# sourceMappingURL=index-BfXpgxk9.d.mts.map
37
+ //# sourceMappingURL=index-DeTwIUKl.d.mts.map
@@ -1,6 +1,6 @@
1
- import { A as WebhookRouteContext, D as WebhookAckMode, d as ResourceDefinition, j as WebhookRouteInput, k as WebhookRoute, u as ResourceBatch } from "./types-xZtSmrGA.mjs";
2
- import { i as Ingestor } from "./service-DLkhuxYl.mjs";
3
- import "./index-CUPP2A_m.mjs";
1
+ import { A as WebhookRouteContext, D as WebhookAckMode, d as ResourceDefinition, j as WebhookRouteInput, k as WebhookRoute, u as ResourceBatch } from "./types-NtSv6gwl.mjs";
2
+ import { i as Ingestor } from "./service-BRoy_EId.mjs";
3
+ import "./index-uFa2wwYo.mjs";
4
4
  import { Context, Queue } from "effect";
5
5
  import { HttpRouter } from "effect/http";
6
6
  //#region src/webhook/server.d.ts
@@ -24,4 +24,4 @@ declare namespace index_d_exports {
24
24
  declare const route: <const Resources extends ReadonlyArray<ResourceDefinition>, Payload>(definition: WebhookRouteInput<Resources, Payload>) => WebhookRoute<Resources, Payload>;
25
25
  //#endregion
26
26
  export { route as n, router as r, index_d_exports as t };
27
- //# sourceMappingURL=index-CRVAwJ5-.d.mts.map
27
+ //# sourceMappingURL=index-dHS59EZl.d.mts.map
@@ -1,4 +1,3 @@
1
- import { E as TableSource } from "./types-xZtSmrGA.mjs";
2
1
  import { Config, Effect, FileSystem } from "effect";
3
2
  import { TableIdentifier } from "iceberg-js";
4
3
  //#region src/runtime-config/error.d.ts
@@ -16,9 +15,11 @@ declare class RuntimeConfigError extends RuntimeConfigError_base<{
16
15
  //#region src/runtime-config/config.d.ts
17
16
  /** Shared HTTP port used by hosted and sandbox connector entrypoints. */
18
17
  declare const httpPort: Config.Config<number>;
19
- /** Wings URL, including the protocol. */
20
- declare const wingsUri: Config.Config<URL>;
21
- /** Wings catalog ID. */
18
+ /** Engine URL, including the protocol. */
19
+ declare const engineUri: Config.Config<URL>;
20
+ /** Arrow Flight URL. Uses the engine URL when unset. */
21
+ declare const flightUri: Config.Config<URL>;
22
+ /** Catalog ID. */
22
23
  declare const catalog: Config.Config<string>;
23
24
  //#endregion
24
25
  //#region src/runtime-config/constants.d.ts
@@ -30,7 +31,8 @@ declare const PlatformRuntimeKey: {
30
31
  readonly connectorInstanceId: "AIRFOIL_CONNECTOR_INSTANCE_ID";
31
32
  readonly stateTable: "AIRFOIL_STATE_TABLE";
32
33
  readonly postgresConnectionString: "POSTGRES_CONNECTION_STRING";
33
- readonly wingsUri: "WINGS_URI";
34
+ readonly engineUri: "ENGINE_URI";
35
+ readonly flightUri: "FLIGHT_URI";
34
36
  readonly catalog: "AIRFOIL_CATALOG";
35
37
  readonly otelEnabled: "OTEL_ENABLED";
36
38
  readonly otelExporterOtlpEndpoint: "OTEL_EXPORTER_OTLP_ENDPOINT";
@@ -58,16 +60,21 @@ declare const PlatformRuntimeDefault: {
58
60
  declare const layerHosted: () => import("effect/Layer").Layer<never, RuntimeConfigError, FileSystem.FileSystem>;
59
61
  //#endregion
60
62
  //#region src/runtime-config/table-bindings.d.ts
63
+ type BindingSource = {
64
+ readonly resources: ReadonlyArray<{
65
+ readonly name: string;
66
+ }>;
67
+ };
61
68
  /** An Iceberg table and its storage location for each connector resource. */
62
69
  type TableBinding = TableIdentifier & {
63
70
  readonly location?: string | undefined;
64
71
  };
65
- type ResolvedTableBindings<Source extends TableSource> = Readonly<Partial<Record<Source["resources"][number]["name"], TableBinding>>>;
72
+ type ResolvedTableBindings<Source extends BindingSource> = Readonly<Partial<Record<Source["resources"][number]["name"], TableBinding>>>;
66
73
  /** Reads hosted table bindings and checks they name resources of the connector. */
67
- declare const loadTableBindings: <const Source extends TableSource>(connector: Source) => Effect.Effect<ResolvedTableBindings<Source>, RuntimeConfigError>;
74
+ declare const loadTableBindings: <const Source extends BindingSource>(connector: Source) => Effect.Effect<ResolvedTableBindings<Source>, RuntimeConfigError>;
68
75
  declare namespace index_d_exports {
69
- export { PlatformRuntimeDefault, PlatformRuntimeKey, ResolvedTableBindings, RuntimeConfigError, RuntimeConfigErrorCode, TableBinding, catalog, httpPort, layerHosted, loadTableBindings, wingsUri };
76
+ export { PlatformRuntimeDefault, PlatformRuntimeKey, ResolvedTableBindings, RuntimeConfigError, RuntimeConfigErrorCode, TableBinding, catalog, engineUri, flightUri, httpPort, layerHosted, loadTableBindings };
70
77
  }
71
78
  //#endregion
72
- export { layerHosted as a, catalog as c, RuntimeConfigError as d, RuntimeConfigErrorCode as f, loadTableBindings as i, httpPort as l, ResolvedTableBindings as n, PlatformRuntimeDefault as o, TableBinding as r, PlatformRuntimeKey as s, index_d_exports as t, wingsUri as u };
73
- //# sourceMappingURL=index-ygpml2kC.d.mts.map
79
+ export { layerHosted as a, catalog as c, httpPort as d, RuntimeConfigError as f, loadTableBindings as i, engineUri as l, ResolvedTableBindings as n, PlatformRuntimeDefault as o, RuntimeConfigErrorCode as p, TableBinding as r, PlatformRuntimeKey as s, index_d_exports as t, flightUri as u };
80
+ //# sourceMappingURL=index-fHIJJoRe.d.mts.map
@@ -0,0 +1,27 @@
1
+ import { t as ConnectorError } from "./index-DkVNO6ks.mjs";
2
+ import { E as TableSource } from "./types-NtSv6gwl.mjs";
3
+ import { a as IngestorService, i as Ingestor, n as IngestResult, r as IngestSource, t as IngestOptions } from "./service-BRoy_EId.mjs";
4
+ import { n as ResolvedTableBindings, t as index_d_exports$1 } from "./index-fHIJJoRe.mjs";
5
+ import { Layer } from "effect";
6
+ import { CatalogManager } from "@useairfoil/api";
7
+ //#region src/ingestor/console.d.ts
8
+ /** Logs batches without sending them over Arrow Flight. */
9
+ declare const layerConsole: Layer.Layer<Ingestor, never, never>;
10
+ //#endregion
11
+ //#region src/ingestor/arrow-flight.d.ts
12
+ /** One catalog and an Iceberg table for each resource that runs. */
13
+ type ArrowFlightIngestorConfig<Source extends TableSource = TableSource> = {
14
+ readonly connector: Source;
15
+ readonly catalog: string;
16
+ readonly tables: ResolvedTableBindings<Source>;
17
+ };
18
+ /** Compiles local schemas and opens one Arrow Flight stream per bound resource. */
19
+ declare const layerArrowFlight: <const Source extends TableSource>(config: ArrowFlightIngestorConfig<Source>) => Layer.Layer<Ingestor, ConnectorError, CatalogManager.CatalogManager>;
20
+ /** Configures Arrow Flight ingestion from the hosted URL, catalog and table bindings. */
21
+ declare const layerArrowFlightConfig: (connector: TableSource) => Layer.Layer<Ingestor, ConnectorError, never>;
22
+ declare namespace index_d_exports {
23
+ export { ArrowFlightIngestorConfig, IngestOptions, IngestResult, IngestSource, Ingestor, IngestorService, layerArrowFlight, layerArrowFlightConfig, layerConsole };
24
+ }
25
+ //#endregion
26
+ export { layerConsole as a, layerArrowFlightConfig as i, ArrowFlightIngestorConfig as n, layerArrowFlight as r, index_d_exports as t };
27
+ //# sourceMappingURL=index-uFa2wwYo.d.mts.map
package/dist/index.d.mts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { t as index_d_exports } from "./index-BX8G7d41.mjs";
2
2
  import { t as ConnectorError } from "./index-DkVNO6ks.mjs";
3
- import { t as Identified } from "./annotations-BE74YmAO.mjs";
4
- import { A as WebhookRouteContext, C as ResourceUpdateOf, D as WebhookAckMode, E as TableSource, O as WebhookHandler, S as ResourceUpdate, T as TableResource, _ as ResourceRequiredField, a as FeedRows, b as ResourceSchema, c as FetchPageResult, d as ResourceDefinition, f as ResourceDelete, g as ResourcePayload, i as Cursor$1, k as WebhookRoute, l as PageFetch, m as ResourceKey, n as ChangesFetch, o as FetchChangesResult, p as ResourceField, r as ConnectorDefinition, s as FetchFeedResult, t as ChangesFeed, u as ResourceBatch, v as ResourceRow, x as ResourceState, y as ResourceRows } from "./types-xZtSmrGA.mjs";
5
- import { c as telemetry_d_exports, d as Fetch, f as Resource, l as Connector, t as index_d_exports$1, u as Cursor } from "./index-NnCutIqM.mjs";
6
- import { t as index_d_exports$2 } from "./index-Dk7urvpF.mjs";
7
- import { t as index_d_exports$3 } from "./index-DJhDp4Xc.mjs";
3
+ import { t as Identified } from "./annotations-vzSzXtr-.mjs";
4
+ import { A as WebhookRouteContext, C as ResourceUpdateOf, D as WebhookAckMode, E as TableSource, O as WebhookHandler, S as ResourceUpdate, T as TableResource, _ as ResourceRequiredField, a as FeedRows, b as ResourceSchema, c as FetchPageResult, d as ResourceDefinition, f as ResourceDelete, g as ResourcePayload, i as Cursor$1, k as WebhookRoute, l as PageFetch, m as ResourceKey, n as ChangesFetch, o as FetchChangesResult, p as ResourceField, r as ConnectorDefinition, s as FetchFeedResult, t as ChangesFeed, u as ResourceBatch, v as ResourceRow, x as ResourceState, y as ResourceRows } from "./types-NtSv6gwl.mjs";
5
+ import { d as Cursor, f as Fetch, l as telemetry_d_exports, p as Resource, t as index_d_exports$1, u as Connector } from "./index-CZKx2Yce.mjs";
6
+ import { t as index_d_exports$2 } from "./index-CV6V6fyx.mjs";
7
+ import { t as index_d_exports$3 } from "./index-BTAbexBp.mjs";
8
8
  import { t as index_d_exports$8 } from "./index-CgvFomO6.mjs";
9
- import { t as index_d_exports$4 } from "./index-BfXpgxk9.mjs";
10
- import { t as index_d_exports$5 } from "./index-CUPP2A_m.mjs";
11
- import { t as index_d_exports$7 } from "./index-ygpml2kC.mjs";
9
+ import { t as index_d_exports$4 } from "./index-DeTwIUKl.mjs";
10
+ import { t as index_d_exports$5 } from "./index-uFa2wwYo.mjs";
11
+ import { t as index_d_exports$7 } from "./index-fHIJJoRe.mjs";
12
12
  import { t as index_d_exports$6 } from "./index-eFuoMZZ3.mjs";
13
- import { h as metrics_d_exports } from "./metrics-CVXFL7YT.mjs";
14
- import { t as index_d_exports$9 } from "./index-BUHSGm9Q.mjs";
15
- import { t as index_d_exports$10 } from "./index-CRVAwJ5-.mjs";
13
+ import { h as metrics_d_exports } from "./metrics-DoJ0WeKu.mjs";
14
+ import { t as index_d_exports$9 } from "./index-Byr8NTdG.mjs";
15
+ import { t as index_d_exports$10 } from "./index-dHS59EZl.mjs";
16
16
  export { index_d_exports as Auth, type ChangesFeed, type ChangesFetch, Connector, index_d_exports$1 as ConnectorApp, type ConnectorDefinition, ConnectorError, Cursor, type Cursor$1 as CursorTypes, index_d_exports$2 as Demo, type FeedRows, Fetch, type FetchChangesResult, type FetchFeedResult, type FetchPageResult, index_d_exports$3 as Iceberg, type Identified, index_d_exports$4 as Ingestion, index_d_exports$5 as Ingestor, index_d_exports$6 as Manifest, metrics_d_exports as Metrics, type PageFetch, Resource, type ResourceBatch, type ResourceDefinition, type ResourceDelete, type ResourceField, type ResourceKey, type ResourcePayload, type ResourceRequiredField, type ResourceRow, type ResourceRows, type ResourceSchema, type ResourceState, type ResourceUpdate, type ResourceUpdateOf, index_d_exports$7 as RuntimeConfig, index_d_exports$8 as StateStore, index_d_exports$9 as Status, type TableResource, type TableSource, telemetry_d_exports as Telemetry, index_d_exports$10 as Webhook, type WebhookAckMode, type WebhookHandler, type WebhookRoute, type WebhookRouteContext };
package/dist/index.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  import { t as ConnectorError } from "./errors-pT0YVJU5.mjs";
2
2
  import { t as auth_exports } from "./auth/index.mjs";
3
- import { t as connector_app_exports } from "./connector-app-C-L4QqG6.mjs";
4
- import { t as runtime_config_exports } from "./runtime-config-Oa55gAew.mjs";
5
- import { t as demo_exports } from "./demo-B30Vlkk2.mjs";
6
- import { o as metrics_exports, w as telemetry_exports } from "./metrics-BaEX__MN.mjs";
7
- import { t as state_store_exports } from "./state-store-uFvHY7Ax.mjs";
8
- import { t as status_exports } from "./status-CKb9IhQ9.mjs";
9
- import { t as ingestion_exports } from "./ingestion-q0WwqUSt.mjs";
10
- import { t as iceberg_exports } from "./iceberg-D6L8I6vA.mjs";
11
- import { t as ingestor_exports } from "./ingestor-D4L-HPkg.mjs";
12
- import { t as manifest_exports } from "./manifest-BGKxmKLy.mjs";
3
+ import { t as connector_app_exports } from "./connector-app-C6_dZnhE.mjs";
4
+ import { t as runtime_config_exports } from "./runtime-config-Bn8Fivt1.mjs";
5
+ import { t as demo_exports } from "./demo-DqTJ7TWI.mjs";
6
+ import { o as metrics_exports, w as telemetry_exports } from "./metrics-C901IIYZ.mjs";
7
+ import { t as state_store_exports } from "./state-store-DhSrKVEH.mjs";
8
+ import { t as status_exports } from "./status-4h6Oxh-O.mjs";
9
+ import { t as ingestion_exports } from "./ingestion-DoCUwm5N.mjs";
10
+ import { t as iceberg_exports } from "./iceberg-Cj2PwlNm.mjs";
11
+ import { t as ingestor_exports } from "./ingestor-DjCEzBzZ.mjs";
12
+ import { t as manifest_exports } from "./manifest-CABeIhAG.mjs";
13
13
  import { t as webhook_exports } from "./webhook/index.mjs";
14
14
  import { DateTime, Effect, Option } from "effect";
15
15
  //#region src/core/builder.ts
@@ -1,2 +1,2 @@
1
- import { n as RunOptions, r as run } from "../index-BfXpgxk9.mjs";
1
+ import { n as RunOptions, r as run } from "../index-DeTwIUKl.mjs";
2
2
  export { type RunOptions, run };
@@ -1,2 +1,2 @@
1
- import { n as run } from "../ingestion-q0WwqUSt.mjs";
1
+ import { n as run } from "../ingestion-DoCUwm5N.mjs";
2
2
  export { run };
@@ -1,11 +1,11 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { t as ConnectorError } from "./errors-pT0YVJU5.mjs";
3
- import { C as annotateError, d as setLastSuccessTimestamp, f as setSyncState, p as setWebhookQueueDepth, v as Attr, x as SpanName } from "./metrics-BaEX__MN.mjs";
3
+ import { C as annotateError, d as setLastSuccessTimestamp, f as setSyncState, p as setWebhookQueueDepth, v as Attr, x as SpanName } from "./metrics-C901IIYZ.mjs";
4
4
  import { t as Ingestor } from "./service-jWxxfEht.mjs";
5
- import { t as ingestBatch } from "./instrumented-Bhp7fyvh.mjs";
6
- import { o as StateStore } from "./state-store-uFvHY7Ax.mjs";
7
- import { c as deriveSyncState, l as hasChanges, s as statusRoute, u as normalizeCursor } from "./status-CKb9IhQ9.mjs";
8
- import { n as router, t as WebhookQueue } from "./server-CMnxz3h0.mjs";
5
+ import { t as ingestBatch } from "./instrumented-Bq1WX2L5.mjs";
6
+ import { o as StateStore } from "./state-store-DhSrKVEH.mjs";
7
+ import { c as deriveSyncState, l as hasChanges, s as statusRoute, u as normalizeCursor } from "./status-4h6Oxh-O.mjs";
8
+ import { n as router, t as WebhookQueue } from "./server-D1TTN0_D.mjs";
9
9
  import { Array, DateTime, Effect, Layer, Order, Queue } from "effect";
10
10
  import { HttpRouter, HttpServerResponse } from "effect/http";
11
11
  import * as Observability from "effect/observability";
@@ -272,4 +272,4 @@ var ingestion_exports = /* @__PURE__ */ __exportAll({ run: () => run });
272
272
  //#endregion
273
273
  export { run as n, ingestion_exports as t };
274
274
 
275
- //# sourceMappingURL=ingestion-q0WwqUSt.mjs.map
275
+ //# sourceMappingURL=ingestion-DoCUwm5N.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ingestion-q0WwqUSt.mjs","names":["Metrics.setWebhookQueueDepth","Metrics.setSyncState","Metrics.setLastSuccessTimestamp","Arr"],"sources":["../src/ingestion/engine.ts","../src/ingestion/index.ts"],"sourcesContent":["import { Array as Arr, DateTime, Effect, Layer, Order, Queue } from \"effect\";\nimport { HttpRouter, type HttpServer, HttpServerResponse } from \"effect/http\";\nimport * as Observability from \"effect/observability\";\n\nimport type {\n ChangesFeed,\n ConnectorDefinition,\n Cursor,\n ResourceDefinition,\n ResourceState,\n WebhookRoute,\n} from \"../core/types\";\nimport type { StateOperation, StateSource } from \"../state-store/schema\";\n\nimport { ConnectorError } from \"../errors\";\nimport { ingestBatch } from \"../ingestor/instrumented\";\nimport { Ingestor } from \"../ingestor/service\";\nimport * as Metrics from \"../metrics\";\nimport { StateStore } from \"../state-store\";\nimport { deriveSyncState, hasChanges, normalizeCursor } from \"../state-store/state\";\nimport { statusRoute } from \"../status\";\nimport { Attr, SpanName, annotateError } from \"../telemetry\";\nimport { router, WebhookQueue, type QueuedWebhookBatch } from \"../webhook/server\";\n\ntype RunBaseOptions = {\n readonly initialCutoff?: Cursor.Value;\n};\n\nexport type RunOptions = RunBaseOptions & {\n readonly webhook?: {\n readonly routes: ReadonlyArray<WebhookRoute>;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n };\n};\n\ntype RunNoWebhookOptions = RunBaseOptions & {\n readonly webhook?: undefined;\n};\n\ntype RunWebhookOptions = RunOptions & {\n readonly webhook: NonNullable<RunOptions[\"webhook\"]>;\n};\n\n/**\n * Runs all connector ingestion loops. Callers provide the Ingestor and\n * StateStore layers; webhook mode additionally requires an HttpServer layer.\n */\nexport function run<const Resources extends ReadonlyArray<ResourceDefinition>>(\n connector: ConnectorDefinition<Resources>,\n options?: RunNoWebhookOptions,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor>;\nexport function run<const Resources extends ReadonlyArray<ResourceDefinition>>(\n connector: ConnectorDefinition<Resources>,\n options: RunWebhookOptions,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor | HttpServer.HttpServer>;\nexport function run(definition: ConnectorDefinition, options?: RunOptions) {\n return Effect.gen(function* () {\n // Check the whole feed, even the resources that don't run.\n if (definition.changes) yield* validateFeed(definition, definition.changes);\n const ingestor = yield* Ingestor;\n const connector = selectResources(definition, ingestor.resourceNames);\n const queueLayer = makeWebhookQueueLayer(connector.name);\n const runtimeLayer = options?.webhook\n ? Layer.mergeAll(\n queueLayer,\n makeWebhookServerLayer(connector, options.webhook).pipe(Layer.provide(queueLayer)),\n )\n : Layer.empty;\n\n return yield* Effect.gen(function* () {\n const initialCutoff =\n options?.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));\n yield* Effect.logInfo(\"Connector started\").pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resources: connector.resources.length,\n }),\n );\n\n const sourceRun = runIngestion(connector, initialCutoff);\n const webhookRun = options?.webhook\n ? runWebhookRuntime(connector, options.webhook.routes)\n : Effect.void;\n\n return yield* Effect.all([sourceRun, webhookRun], { concurrency: \"unbounded\" }).pipe(\n Effect.asVoid,\n );\n }).pipe(Effect.provide(runtimeLayer));\n });\n}\n\nconst selectResources = (\n connector: ConnectorDefinition,\n names: ReadonlyArray<string> | undefined,\n): ConnectorDefinition => {\n if (names === undefined) return connector;\n const isSelected = (resource: ResourceDefinition) => names.includes(resource.name);\n const { changes, ...rest } = connector;\n const feedResources = changes?.resources.filter(isSelected) ?? [];\n return {\n ...rest,\n resources: connector.resources.filter(isSelected),\n ...(changes && feedResources.length > 0\n ? { changes: { ...changes, resources: feedResources } }\n : {}),\n };\n};\n\nconst makeWebhookQueueLayer = (connector: string): Layer.Layer<WebhookQueue> =>\n Layer.effect(WebhookQueue)(\n Effect.gen(function* () {\n const queue = yield* Queue.bounded<QueuedWebhookBatch>(1024);\n yield* Metrics.setWebhookQueueDepth(connector, 0);\n return WebhookQueue.of({ queue });\n }),\n );\n\nconst runWebhookRuntime = (connector: ConnectorDefinition, routes: ReadonlyArray<WebhookRoute>) => {\n const hasAfterEnqueue = routes.some((route) => route.ackMode === \"after-enqueue\");\n return Effect.all(\n [hasAfterEnqueue ? runWebhookQueueConsumer(connector) : Effect.void, Effect.never],\n {\n concurrency: \"unbounded\",\n },\n ).pipe(Effect.asVoid);\n};\n\nconst runWebhookQueueConsumer = (connector: ConnectorDefinition) =>\n Effect.gen(function* () {\n const queue = yield* WebhookQueue;\n while (true) {\n const batch = yield* Queue.take(queue.queue);\n const depth = yield* Queue.size(queue.queue);\n yield* Metrics.setWebhookQueueDepth(connector.name, depth);\n yield* ingestBatch({\n connector: connector.name,\n resource: batch.resource,\n source: \"webhook\",\n batch: batch.batch,\n });\n }\n });\n\nconst makeWebhookServerLayer = (\n connector: ConnectorDefinition,\n options: {\n readonly routes: ReadonlyArray<WebhookRoute>;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n },\n): Layer.Layer<never, never, HttpServer.HttpServer> => {\n const healthPath: HttpRouter.PathInput = options.healthPath ?? \"/health\";\n const metricsPath = options.metricsPath === undefined ? \"/metrics\" : options.metricsPath;\n const statusPath = options.statusPath === undefined ? \"/status\" : options.statusPath;\n const app = Layer.mergeAll(\n router(options.routes, {\n connectorName: connector.name,\n resourceNames: connector.resources.map((resource) => resource.name),\n }),\n HttpRouter.add(\"GET\", healthPath, Effect.succeed(HttpServerResponse.text(\"ok\"))),\n ...(metricsPath === false\n ? []\n : [Observability.PrometheusMetrics.layerHttp({ path: metricsPath })]),\n ...(statusPath === false ? [] : [statusRoute(connector, statusPath)]),\n );\n\n return HttpRouter.serve(app, {\n disableLogger: options.disableHttpLogger ?? true,\n });\n};\n\nconst runIngestion = (\n connector: ConnectorDefinition,\n initialCutoff: Cursor.Value,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor> =>\n Effect.gen(function* () {\n const feed = connector.changes;\n yield* Effect.all(\n [\n Effect.forEach(\n connector.resources,\n (resource) => runResourceSources(connector, resource, initialCutoff),\n { concurrency: \"unbounded\" },\n ),\n feed ? runChangesFeed(connector, feed, initialCutoff) : Effect.void,\n ],\n { concurrency: \"unbounded\" },\n );\n });\n\nconst bySavedAt = Order.mapInput(\n Order.String,\n (state: NonNullable<ResourceState[\"changes\"]>) => state.lastSuccessAt ?? \"\",\n);\n\nconst validateFeed = (connector: ConnectorDefinition, feed: ChangesFeed) =>\n Effect.forEach(feed.resources, (member, index) => {\n if (feed.resources.findIndex((item) => item.name === member.name) !== index) {\n return Effect.fail(\n new ConnectorError({ message: `Resource ${member.name} is in the changes feed twice` }),\n );\n }\n const resource = connector.resources.find((item) => item.name === member.name);\n if (!resource) {\n return Effect.fail(\n new ConnectorError({\n message: `Changes feed resource ${member.name} is not a resource of connector ${connector.name}`,\n }),\n );\n }\n if (resource.changes) {\n return Effect.fail(\n new ConnectorError({\n message: `Resource ${member.name} has its own changes and is also in the changes feed`,\n }),\n );\n }\n return Effect.void;\n }).pipe(\n Effect.andThen(\n feed.resources.length === 0\n ? Effect.fail(new ConnectorError({ message: \"The changes feed has no resources\" }))\n : Effect.void,\n ),\n );\n\nconst initializeResourceState = (\n existing: ResourceState | undefined,\n initialCutoff: Cursor.Value,\n): ResourceState => ({\n ...existing,\n changes: existing?.changes ?? { cursor: initialCutoff },\n backfill: existing?.backfill ?? {\n cutoff: initialCutoff,\n completed: false,\n },\n});\n\nconst getInitializedState = Effect.fnUntraced(function* (\n resource: string,\n initialCutoff: Cursor.Value,\n) {\n const store = yield* StateStore;\n const existing = yield* store.getResourceState(resource);\n return initializeResourceState(existing, initialCutoff);\n});\n\nconst runResourceSources = (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) => {\n const runs = [\n resource.backfill\n ? isolateSourceFailure(\n runBackfill(connector, resource, initialCutoff),\n connector,\n resource,\n \"backfill\",\n )\n : Effect.void,\n resource.changes\n ? isolateSourceFailure(\n runChanges(connector, resource, initialCutoff),\n connector,\n resource,\n \"changes\",\n )\n : Effect.void,\n ];\n\n return initializeRuntimeStatus(connector, resource, initialCutoff).pipe(\n Effect.andThen(Effect.all(runs, { concurrency: \"unbounded\" })),\n Effect.asVoid,\n Effect.catch((error) =>\n Metrics.setSyncState({ connector: connector.name, resource: resource.name }, \"error\").pipe(\n Effect.andThen(Effect.logError(\"Connector resource initialization failed\", error)),\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resource: resource.name,\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n};\n\nconst recordResourceError =\n (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n source: StateSource,\n operation: StateOperation,\n ) =>\n <A, R>(\n effect: Effect.Effect<A, ConnectorError, R>,\n ): Effect.Effect<A, ConnectorError, R | StateStore> =>\n effect.pipe(\n Effect.tapError(() =>\n Metrics.setSyncState({ connector: connector.name, resource: resource.name }, \"error\").pipe(\n Effect.andThen(\n StateStore.pipe(\n Effect.flatMap((store) => store.setResourceError(resource.name, source, operation)),\n ),\n ),\n ),\n ),\n );\n\nconst isolateSourceFailure = <A, R>(\n effect: Effect.Effect<A, ConnectorError, R>,\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n source: StateSource,\n): Effect.Effect<A, never, R> =>\n // Only typed source errors are isolated. Defects and interruption still stop the runtime.\n effect.pipe(\n Effect.catch((error) =>\n Effect.logError(\"Connector source parked\", error).pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resource: resource.name,\n source,\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n\nconst refreshRuntimeStatus = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n yield* Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n deriveSyncState(connector, resource, state),\n );\n\n return state;\n});\n\nconst initializeRuntimeStatus = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n yield* Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n deriveSyncState(connector, resource, state),\n );\n\n if (resource.backfill) {\n yield* Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"backfill\" },\n state.backfill?.lastSuccessAt,\n );\n }\n if (hasChanges(connector, resource)) {\n yield* Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n state.changes?.lastSuccessAt,\n );\n }\n});\n\nconst runBackfill = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n if (!resource.backfill) return;\n const store = yield* StateStore;\n let state = yield* getInitializedState(resource.name, initialCutoff);\n\n if (state.backfill?.completed === true) {\n // The checkpoint may have committed before the previous process cleared\n // its error marker. It may also be hidden by a newer changes error.\n yield* store\n .clearResourceError(resource.name, \"backfill\")\n .pipe(recordResourceError(connector, resource, \"backfill\", \"checkpoint\"));\n yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n return;\n }\n\n while (state.backfill?.completed !== true) {\n const backfill = state.backfill ?? { cutoff: initialCutoff, completed: false };\n const clearsVisibleError = state.lastError?.source === \"backfill\";\n const page = yield* resource.backfill\n .fetch({\n pageCursor: backfill.pageCursor,\n cutoff: backfill.cutoff,\n })\n .pipe(recordResourceError(connector, resource, \"backfill\", \"fetch\"));\n\n yield* ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"backfill\",\n batch: {\n cursor: page.nextPageCursor ?? backfill.cutoff,\n rows: page.rows,\n },\n }).pipe(recordResourceError(connector, resource, \"backfill\", \"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n state = {\n ...state,\n backfill: {\n cutoff: backfill.cutoff,\n pageCursor: page.nextPageCursor,\n completed: !page.hasMore,\n lastSuccessAt,\n },\n };\n\n // Checkpoint only after ingestion succeeds so a crash cannot skip an\n // unacknowledged page; replay therefore remains at-least-once.\n yield* Effect.withSpan(\n store\n .setBackfillState(resource.name, {\n cutoff: normalizeCursor(backfill.cutoff),\n pageCursor:\n page.nextPageCursor === undefined ? undefined : normalizeCursor(page.nextPageCursor),\n completed: !page.hasMore,\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"backfill\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"backfill\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ).pipe(recordResourceError(connector, resource, \"backfill\", \"checkpoint\"));\n\n // Completion or clearing an error can change the resource-wide sync state.\n if (clearsVisibleError || !page.hasMore) {\n state = yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n }\n }\n});\n\nconst runChanges = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n if (!resource.changes) return;\n const store = yield* StateStore;\n\n while (true) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n const cursor = state.changes?.cursor ?? initialCutoff;\n const clearsVisibleError = state.lastError?.source === \"changes\";\n const page = yield* resource.changes\n .fetch({ cursor })\n .pipe(recordResourceError(connector, resource, \"changes\", \"fetch\"));\n\n yield* ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"changes\",\n batch: {\n cursor: page.cursor,\n rows: page.rows,\n },\n }).pipe(recordResourceError(connector, resource, \"changes\", \"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n // Advance the durable cursor only after Wings acknowledges the page.\n yield* Effect.withSpan(\n store\n .setChangesState(resource.name, {\n cursor: normalizeCursor(page.cursor),\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"changes\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ).pipe(recordResourceError(connector, resource, \"changes\", \"checkpoint\"));\n\n if (clearsVisibleError) {\n yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n }\n\n if (!page.hasMore) {\n yield* Effect.sleep(resource.changes.interval ?? \"1 minute\");\n }\n }\n});\n\n// Every member resource stores the feed cursor. All rows are ingested before any\n// cursor is written. If a crash stops the writes partway, the next run starts\n// from the oldest cursor.\nconst runChangesFeed = (\n connector: ConnectorDefinition,\n feed: ChangesFeed,\n initialCutoff: Cursor.Value,\n): Effect.Effect<void, never, StateStore | Ingestor> =>\n Effect.gen(function* () {\n const store = yield* StateStore;\n const members = feed.resources;\n const selected = new Set(members.map((resource) => resource.name));\n // Any failure stops the whole feed, so it is an error for every resource in it.\n const recordFeedError =\n (operation: StateOperation) =>\n <A, R>(effect: Effect.Effect<A, ConnectorError, R>) =>\n effect.pipe(\n Effect.tapError(() =>\n Effect.forEach(\n members,\n (resource) =>\n Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n \"error\",\n ).pipe(Effect.andThen(store.setResourceError(resource.name, \"changes\", operation))),\n { discard: true },\n ),\n ),\n );\n\n while (true) {\n const states = yield* Effect.forEach(members, (resource) =>\n store.getResourceState(resource.name),\n );\n // A resource that was off has an older cursor. Resume from the oldest, so it\n // gets the changes it missed. The others read some changes again.\n const saved = states.flatMap((state) => (state?.changes ? [state.changes] : []));\n const cursor = Arr.isReadonlyArrayNonEmpty(saved)\n ? Arr.min(saved, bySavedAt).cursor\n : initialCutoff;\n const result = yield* feed.fetch({ cursor, selected }).pipe(recordFeedError(\"fetch\"));\n\n yield* Effect.forEach(\n members,\n (resource) =>\n ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"changes\",\n batch: {\n cursor: result.cursor,\n rows: result.rows[resource.name] ?? [],\n },\n }),\n { discard: true },\n ).pipe(recordFeedError(\"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n yield* Effect.forEach(\n members,\n (resource) =>\n Effect.withSpan(\n store\n .setChangesState(resource.name, {\n cursor: normalizeCursor(result.cursor),\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"changes\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ),\n { discard: true },\n ).pipe(recordFeedError(\"checkpoint\"));\n\n yield* Effect.forEach(members, (resource, index) =>\n states[index]?.lastError?.source === \"changes\"\n ? refreshRuntimeStatus(connector, resource, initialCutoff)\n : Effect.void,\n );\n\n if (!result.hasMore) {\n yield* Effect.sleep(feed.interval ?? \"1 minute\");\n }\n }\n }).pipe(\n // Only typed errors park the feed. Defects and interruption still stop the runtime.\n Effect.catch((error) =>\n Effect.logError(\"Connector changes feed parked\", error).pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resources: feed.resources.map((resource) => resource.name).join(\",\"),\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n","export { run, type RunOptions } from \"./engine\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"ingestion-DoCUwm5N.mjs","names":["Metrics.setWebhookQueueDepth","Metrics.setSyncState","Metrics.setLastSuccessTimestamp","Arr"],"sources":["../src/ingestion/engine.ts","../src/ingestion/index.ts"],"sourcesContent":["import { Array as Arr, DateTime, Effect, Layer, Order, Queue } from \"effect\";\nimport { HttpRouter, type HttpServer, HttpServerResponse } from \"effect/http\";\nimport * as Observability from \"effect/observability\";\n\nimport type {\n ChangesFeed,\n ConnectorDefinition,\n Cursor,\n ResourceDefinition,\n ResourceState,\n WebhookRoute,\n} from \"../core/types\";\nimport type { StateOperation, StateSource } from \"../state-store/schema\";\n\nimport { ConnectorError } from \"../errors\";\nimport { ingestBatch } from \"../ingestor/instrumented\";\nimport { Ingestor } from \"../ingestor/service\";\nimport * as Metrics from \"../metrics\";\nimport { StateStore } from \"../state-store\";\nimport { deriveSyncState, hasChanges, normalizeCursor } from \"../state-store/state\";\nimport { statusRoute } from \"../status\";\nimport { Attr, SpanName, annotateError } from \"../telemetry\";\nimport { router, WebhookQueue, type QueuedWebhookBatch } from \"../webhook/server\";\n\ntype RunBaseOptions = {\n readonly initialCutoff?: Cursor.Value;\n};\n\nexport type RunOptions = RunBaseOptions & {\n readonly webhook?: {\n readonly routes: ReadonlyArray<WebhookRoute>;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n };\n};\n\ntype RunNoWebhookOptions = RunBaseOptions & {\n readonly webhook?: undefined;\n};\n\ntype RunWebhookOptions = RunOptions & {\n readonly webhook: NonNullable<RunOptions[\"webhook\"]>;\n};\n\n/**\n * Runs all connector ingestion loops. Callers provide the Ingestor and\n * StateStore layers; webhook mode additionally requires an HttpServer layer.\n */\nexport function run<const Resources extends ReadonlyArray<ResourceDefinition>>(\n connector: ConnectorDefinition<Resources>,\n options?: RunNoWebhookOptions,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor>;\nexport function run<const Resources extends ReadonlyArray<ResourceDefinition>>(\n connector: ConnectorDefinition<Resources>,\n options: RunWebhookOptions,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor | HttpServer.HttpServer>;\nexport function run(definition: ConnectorDefinition, options?: RunOptions) {\n return Effect.gen(function* () {\n // Check the whole feed, even the resources that don't run.\n if (definition.changes) yield* validateFeed(definition, definition.changes);\n const ingestor = yield* Ingestor;\n const connector = selectResources(definition, ingestor.resourceNames);\n const queueLayer = makeWebhookQueueLayer(connector.name);\n const runtimeLayer = options?.webhook\n ? Layer.mergeAll(\n queueLayer,\n makeWebhookServerLayer(connector, options.webhook).pipe(Layer.provide(queueLayer)),\n )\n : Layer.empty;\n\n return yield* Effect.gen(function* () {\n const initialCutoff =\n options?.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));\n yield* Effect.logInfo(\"Connector started\").pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resources: connector.resources.length,\n }),\n );\n\n const sourceRun = runIngestion(connector, initialCutoff);\n const webhookRun = options?.webhook\n ? runWebhookRuntime(connector, options.webhook.routes)\n : Effect.void;\n\n return yield* Effect.all([sourceRun, webhookRun], { concurrency: \"unbounded\" }).pipe(\n Effect.asVoid,\n );\n }).pipe(Effect.provide(runtimeLayer));\n });\n}\n\nconst selectResources = (\n connector: ConnectorDefinition,\n names: ReadonlyArray<string> | undefined,\n): ConnectorDefinition => {\n if (names === undefined) return connector;\n const isSelected = (resource: ResourceDefinition) => names.includes(resource.name);\n const { changes, ...rest } = connector;\n const feedResources = changes?.resources.filter(isSelected) ?? [];\n return {\n ...rest,\n resources: connector.resources.filter(isSelected),\n ...(changes && feedResources.length > 0\n ? { changes: { ...changes, resources: feedResources } }\n : {}),\n };\n};\n\nconst makeWebhookQueueLayer = (connector: string): Layer.Layer<WebhookQueue> =>\n Layer.effect(WebhookQueue)(\n Effect.gen(function* () {\n const queue = yield* Queue.bounded<QueuedWebhookBatch>(1024);\n yield* Metrics.setWebhookQueueDepth(connector, 0);\n return WebhookQueue.of({ queue });\n }),\n );\n\nconst runWebhookRuntime = (connector: ConnectorDefinition, routes: ReadonlyArray<WebhookRoute>) => {\n const hasAfterEnqueue = routes.some((route) => route.ackMode === \"after-enqueue\");\n return Effect.all(\n [hasAfterEnqueue ? runWebhookQueueConsumer(connector) : Effect.void, Effect.never],\n {\n concurrency: \"unbounded\",\n },\n ).pipe(Effect.asVoid);\n};\n\nconst runWebhookQueueConsumer = (connector: ConnectorDefinition) =>\n Effect.gen(function* () {\n const queue = yield* WebhookQueue;\n while (true) {\n const batch = yield* Queue.take(queue.queue);\n const depth = yield* Queue.size(queue.queue);\n yield* Metrics.setWebhookQueueDepth(connector.name, depth);\n yield* ingestBatch({\n connector: connector.name,\n resource: batch.resource,\n source: \"webhook\",\n batch: batch.batch,\n });\n }\n });\n\nconst makeWebhookServerLayer = (\n connector: ConnectorDefinition,\n options: {\n readonly routes: ReadonlyArray<WebhookRoute>;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n },\n): Layer.Layer<never, never, HttpServer.HttpServer> => {\n const healthPath: HttpRouter.PathInput = options.healthPath ?? \"/health\";\n const metricsPath = options.metricsPath === undefined ? \"/metrics\" : options.metricsPath;\n const statusPath = options.statusPath === undefined ? \"/status\" : options.statusPath;\n const app = Layer.mergeAll(\n router(options.routes, {\n connectorName: connector.name,\n resourceNames: connector.resources.map((resource) => resource.name),\n }),\n HttpRouter.add(\"GET\", healthPath, Effect.succeed(HttpServerResponse.text(\"ok\"))),\n ...(metricsPath === false\n ? []\n : [Observability.PrometheusMetrics.layerHttp({ path: metricsPath })]),\n ...(statusPath === false ? [] : [statusRoute(connector, statusPath)]),\n );\n\n return HttpRouter.serve(app, {\n disableLogger: options.disableHttpLogger ?? true,\n });\n};\n\nconst runIngestion = (\n connector: ConnectorDefinition,\n initialCutoff: Cursor.Value,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor> =>\n Effect.gen(function* () {\n const feed = connector.changes;\n yield* Effect.all(\n [\n Effect.forEach(\n connector.resources,\n (resource) => runResourceSources(connector, resource, initialCutoff),\n { concurrency: \"unbounded\" },\n ),\n feed ? runChangesFeed(connector, feed, initialCutoff) : Effect.void,\n ],\n { concurrency: \"unbounded\" },\n );\n });\n\nconst bySavedAt = Order.mapInput(\n Order.String,\n (state: NonNullable<ResourceState[\"changes\"]>) => state.lastSuccessAt ?? \"\",\n);\n\nconst validateFeed = (connector: ConnectorDefinition, feed: ChangesFeed) =>\n Effect.forEach(feed.resources, (member, index) => {\n if (feed.resources.findIndex((item) => item.name === member.name) !== index) {\n return Effect.fail(\n new ConnectorError({ message: `Resource ${member.name} is in the changes feed twice` }),\n );\n }\n const resource = connector.resources.find((item) => item.name === member.name);\n if (!resource) {\n return Effect.fail(\n new ConnectorError({\n message: `Changes feed resource ${member.name} is not a resource of connector ${connector.name}`,\n }),\n );\n }\n if (resource.changes) {\n return Effect.fail(\n new ConnectorError({\n message: `Resource ${member.name} has its own changes and is also in the changes feed`,\n }),\n );\n }\n return Effect.void;\n }).pipe(\n Effect.andThen(\n feed.resources.length === 0\n ? Effect.fail(new ConnectorError({ message: \"The changes feed has no resources\" }))\n : Effect.void,\n ),\n );\n\nconst initializeResourceState = (\n existing: ResourceState | undefined,\n initialCutoff: Cursor.Value,\n): ResourceState => ({\n ...existing,\n changes: existing?.changes ?? { cursor: initialCutoff },\n backfill: existing?.backfill ?? {\n cutoff: initialCutoff,\n completed: false,\n },\n});\n\nconst getInitializedState = Effect.fnUntraced(function* (\n resource: string,\n initialCutoff: Cursor.Value,\n) {\n const store = yield* StateStore;\n const existing = yield* store.getResourceState(resource);\n return initializeResourceState(existing, initialCutoff);\n});\n\nconst runResourceSources = (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) => {\n const runs = [\n resource.backfill\n ? isolateSourceFailure(\n runBackfill(connector, resource, initialCutoff),\n connector,\n resource,\n \"backfill\",\n )\n : Effect.void,\n resource.changes\n ? isolateSourceFailure(\n runChanges(connector, resource, initialCutoff),\n connector,\n resource,\n \"changes\",\n )\n : Effect.void,\n ];\n\n return initializeRuntimeStatus(connector, resource, initialCutoff).pipe(\n Effect.andThen(Effect.all(runs, { concurrency: \"unbounded\" })),\n Effect.asVoid,\n Effect.catch((error) =>\n Metrics.setSyncState({ connector: connector.name, resource: resource.name }, \"error\").pipe(\n Effect.andThen(Effect.logError(\"Connector resource initialization failed\", error)),\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resource: resource.name,\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n};\n\nconst recordResourceError =\n (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n source: StateSource,\n operation: StateOperation,\n ) =>\n <A, R>(\n effect: Effect.Effect<A, ConnectorError, R>,\n ): Effect.Effect<A, ConnectorError, R | StateStore> =>\n effect.pipe(\n Effect.tapError(() =>\n Metrics.setSyncState({ connector: connector.name, resource: resource.name }, \"error\").pipe(\n Effect.andThen(\n StateStore.pipe(\n Effect.flatMap((store) => store.setResourceError(resource.name, source, operation)),\n ),\n ),\n ),\n ),\n );\n\nconst isolateSourceFailure = <A, R>(\n effect: Effect.Effect<A, ConnectorError, R>,\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n source: StateSource,\n): Effect.Effect<A, never, R> =>\n // Only typed source errors are isolated. Defects and interruption still stop the runtime.\n effect.pipe(\n Effect.catch((error) =>\n Effect.logError(\"Connector source parked\", error).pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resource: resource.name,\n source,\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n\nconst refreshRuntimeStatus = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n yield* Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n deriveSyncState(connector, resource, state),\n );\n\n return state;\n});\n\nconst initializeRuntimeStatus = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n yield* Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n deriveSyncState(connector, resource, state),\n );\n\n if (resource.backfill) {\n yield* Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"backfill\" },\n state.backfill?.lastSuccessAt,\n );\n }\n if (hasChanges(connector, resource)) {\n yield* Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n state.changes?.lastSuccessAt,\n );\n }\n});\n\nconst runBackfill = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n if (!resource.backfill) return;\n const store = yield* StateStore;\n let state = yield* getInitializedState(resource.name, initialCutoff);\n\n if (state.backfill?.completed === true) {\n // The checkpoint may have committed before the previous process cleared\n // its error marker. It may also be hidden by a newer changes error.\n yield* store\n .clearResourceError(resource.name, \"backfill\")\n .pipe(recordResourceError(connector, resource, \"backfill\", \"checkpoint\"));\n yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n return;\n }\n\n while (state.backfill?.completed !== true) {\n const backfill = state.backfill ?? { cutoff: initialCutoff, completed: false };\n const clearsVisibleError = state.lastError?.source === \"backfill\";\n const page = yield* resource.backfill\n .fetch({\n pageCursor: backfill.pageCursor,\n cutoff: backfill.cutoff,\n })\n .pipe(recordResourceError(connector, resource, \"backfill\", \"fetch\"));\n\n yield* ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"backfill\",\n batch: {\n cursor: page.nextPageCursor ?? backfill.cutoff,\n rows: page.rows,\n },\n }).pipe(recordResourceError(connector, resource, \"backfill\", \"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n state = {\n ...state,\n backfill: {\n cutoff: backfill.cutoff,\n pageCursor: page.nextPageCursor,\n completed: !page.hasMore,\n lastSuccessAt,\n },\n };\n\n // Checkpoint only after ingestion succeeds so a crash cannot skip an\n // unacknowledged page; replay therefore remains at-least-once.\n yield* Effect.withSpan(\n store\n .setBackfillState(resource.name, {\n cutoff: normalizeCursor(backfill.cutoff),\n pageCursor:\n page.nextPageCursor === undefined ? undefined : normalizeCursor(page.nextPageCursor),\n completed: !page.hasMore,\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"backfill\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"backfill\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ).pipe(recordResourceError(connector, resource, \"backfill\", \"checkpoint\"));\n\n // Completion or clearing an error can change the resource-wide sync state.\n if (clearsVisibleError || !page.hasMore) {\n state = yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n }\n }\n});\n\nconst runChanges = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n if (!resource.changes) return;\n const store = yield* StateStore;\n\n while (true) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n const cursor = state.changes?.cursor ?? initialCutoff;\n const clearsVisibleError = state.lastError?.source === \"changes\";\n const page = yield* resource.changes\n .fetch({ cursor })\n .pipe(recordResourceError(connector, resource, \"changes\", \"fetch\"));\n\n yield* ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"changes\",\n batch: {\n cursor: page.cursor,\n rows: page.rows,\n },\n }).pipe(recordResourceError(connector, resource, \"changes\", \"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n // Advance the durable cursor only after the engine acknowledges the page.\n yield* Effect.withSpan(\n store\n .setChangesState(resource.name, {\n cursor: normalizeCursor(page.cursor),\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"changes\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ).pipe(recordResourceError(connector, resource, \"changes\", \"checkpoint\"));\n\n if (clearsVisibleError) {\n yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n }\n\n if (!page.hasMore) {\n yield* Effect.sleep(resource.changes.interval ?? \"1 minute\");\n }\n }\n});\n\n// Every member resource stores the feed cursor. All rows are ingested before any\n// cursor is written. If a crash stops the writes partway, the next run starts\n// from the oldest cursor.\nconst runChangesFeed = (\n connector: ConnectorDefinition,\n feed: ChangesFeed,\n initialCutoff: Cursor.Value,\n): Effect.Effect<void, never, StateStore | Ingestor> =>\n Effect.gen(function* () {\n const store = yield* StateStore;\n const members = feed.resources;\n const selected = new Set(members.map((resource) => resource.name));\n // Any failure stops the whole feed, so it is an error for every resource in it.\n const recordFeedError =\n (operation: StateOperation) =>\n <A, R>(effect: Effect.Effect<A, ConnectorError, R>) =>\n effect.pipe(\n Effect.tapError(() =>\n Effect.forEach(\n members,\n (resource) =>\n Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n \"error\",\n ).pipe(Effect.andThen(store.setResourceError(resource.name, \"changes\", operation))),\n { discard: true },\n ),\n ),\n );\n\n while (true) {\n const states = yield* Effect.forEach(members, (resource) =>\n store.getResourceState(resource.name),\n );\n // A resource that was off has an older cursor. Resume from the oldest, so it\n // gets the changes it missed. The others read some changes again.\n const saved = states.flatMap((state) => (state?.changes ? [state.changes] : []));\n const cursor = Arr.isReadonlyArrayNonEmpty(saved)\n ? Arr.min(saved, bySavedAt).cursor\n : initialCutoff;\n const result = yield* feed.fetch({ cursor, selected }).pipe(recordFeedError(\"fetch\"));\n\n yield* Effect.forEach(\n members,\n (resource) =>\n ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"changes\",\n batch: {\n cursor: result.cursor,\n rows: result.rows[resource.name] ?? [],\n },\n }),\n { discard: true },\n ).pipe(recordFeedError(\"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n yield* Effect.forEach(\n members,\n (resource) =>\n Effect.withSpan(\n store\n .setChangesState(resource.name, {\n cursor: normalizeCursor(result.cursor),\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"changes\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ),\n { discard: true },\n ).pipe(recordFeedError(\"checkpoint\"));\n\n yield* Effect.forEach(members, (resource, index) =>\n states[index]?.lastError?.source === \"changes\"\n ? refreshRuntimeStatus(connector, resource, initialCutoff)\n : Effect.void,\n );\n\n if (!result.hasMore) {\n yield* Effect.sleep(feed.interval ?? \"1 minute\");\n }\n }\n }).pipe(\n // Only typed errors park the feed. Defects and interruption still stop the runtime.\n Effect.catch((error) =>\n Effect.logError(\"Connector changes feed parked\", error).pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resources: feed.resources.map((resource) => resource.name).join(\",\"),\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n","export { run, type RunOptions } from \"./engine\";\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { a as IngestorService, i as Ingestor, n as IngestResult, r as IngestSource, t as IngestOptions } from "../service-DLkhuxYl.mjs";
2
- import { a as layerConsole, i as layerWingsConfig, n as WingsIngestorConfig, r as layerWings } from "../index-CUPP2A_m.mjs";
3
- export { type IngestOptions, type IngestResult, type IngestSource, Ingestor, type IngestorService, type WingsIngestorConfig, layerConsole, layerWings, layerWingsConfig };
1
+ import { a as IngestorService, i as Ingestor, n as IngestResult, r as IngestSource, t as IngestOptions } from "../service-BRoy_EId.mjs";
2
+ import { a as layerConsole, i as layerArrowFlightConfig, n as ArrowFlightIngestorConfig, r as layerArrowFlight } from "../index-uFa2wwYo.mjs";
3
+ export { type ArrowFlightIngestorConfig, type IngestOptions, type IngestResult, type IngestSource, Ingestor, type IngestorService, layerArrowFlight, layerArrowFlightConfig, layerConsole };
@@ -1,4 +1,4 @@
1
- import { n as layerWingsConfig, t as layerWings } from "../wings-I56hGtNv.mjs";
2
1
  import { t as Ingestor } from "../service-jWxxfEht.mjs";
3
- import { n as layerConsole } from "../ingestor-D4L-HPkg.mjs";
4
- export { Ingestor, layerConsole, layerWings, layerWingsConfig };
2
+ import { n as layerArrowFlightConfig, t as layerArrowFlight } from "../arrow-flight-DDQ0ktx9.mjs";
3
+ import { n as layerConsole } from "../ingestor-DjCEzBzZ.mjs";
4
+ export { Ingestor, layerArrowFlight, layerArrowFlightConfig, layerConsole };