@useairfoil/connector-kit 0.5.3 → 0.6.1

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 (178) hide show
  1. package/METRICS.md +20 -19
  2. package/README.md +127 -430
  3. package/dist/annotations-BE74YmAO.d.mts +39 -0
  4. package/dist/auth/index.d.mts +2 -0
  5. package/dist/{auth-DvU_CZ7C.js → auth/index.mjs} +6 -8
  6. package/dist/auth/index.mjs.map +1 -0
  7. package/dist/connector-app/index.d.mts +2 -0
  8. package/dist/connector-app/index.mjs +2 -0
  9. package/dist/connector-app-C-L4QqG6.mjs +123 -0
  10. package/dist/connector-app-C-L4QqG6.mjs.map +1 -0
  11. package/dist/{constants-BRhIX_rz.js → constants-D-GQzpHZ.mjs} +10 -6
  12. package/dist/constants-D-GQzpHZ.mjs.map +1 -0
  13. package/dist/demo/index.d.mts +2 -0
  14. package/dist/demo/index.mjs +2 -0
  15. package/dist/demo-B30Vlkk2.mjs +191 -0
  16. package/dist/demo-B30Vlkk2.mjs.map +1 -0
  17. package/dist/errors/index.d.mts +2 -0
  18. package/dist/errors/index.mjs +2 -0
  19. package/dist/{errors-DHWylqRZ.js → errors-pT0YVJU5.mjs} +2 -3
  20. package/dist/errors-pT0YVJU5.mjs.map +1 -0
  21. package/dist/iceberg/index.d.mts +3 -0
  22. package/dist/iceberg/index.mjs +3 -0
  23. package/dist/iceberg-D6L8I6vA.mjs +39 -0
  24. package/dist/iceberg-D6L8I6vA.mjs.map +1 -0
  25. package/dist/{index-Cq2IzY7T.d.ts → index-BUHSGm9Q.d.mts} +11 -13
  26. package/dist/{index-CTHVudvQ.d.ts → index-BX8G7d41.d.mts} +1 -2
  27. package/dist/{index-J42AZaXU.d.ts → index-BfXpgxk9.d.mts} +9 -10
  28. package/dist/{index-DKWIh6M1.d.ts → index-CRVAwJ5-.d.mts} +10 -8
  29. package/dist/index-CUPP2A_m.d.mts +27 -0
  30. package/dist/{index-Coh_SkBs.d.ts → index-CgvFomO6.d.mts} +6 -7
  31. package/dist/index-DJhDp4Xc.d.mts +58 -0
  32. package/dist/index-Dk7urvpF.d.mts +76 -0
  33. package/dist/{index-D54ySAKn.d.ts → index-DkVNO6ks.d.mts} +2 -5
  34. package/dist/{index-DtJX_tic.d.ts → index-NnCutIqM.d.mts} +77 -38
  35. package/dist/{index-CBT-JX-T.d.ts → index-eFuoMZZ3.d.mts} +18 -20
  36. package/dist/index-ygpml2kC.d.mts +73 -0
  37. package/dist/index.d.mts +16 -0
  38. package/dist/index.mjs +45 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/ingestion/index.d.mts +2 -0
  41. package/dist/ingestion/index.mjs +2 -0
  42. package/dist/ingestion-q0WwqUSt.mjs +275 -0
  43. package/dist/ingestion-q0WwqUSt.mjs.map +1 -0
  44. package/dist/ingestor/index.d.mts +3 -0
  45. package/dist/ingestor/index.mjs +4 -0
  46. package/dist/ingestor-D4L-HPkg.mjs +26 -0
  47. package/dist/ingestor-D4L-HPkg.mjs.map +1 -0
  48. package/dist/instrumented-Bhp7fyvh.mjs +29 -0
  49. package/dist/instrumented-Bhp7fyvh.mjs.map +1 -0
  50. package/dist/manifest/index.d.mts +2 -0
  51. package/dist/manifest/{index.js → index.mjs} +2 -4
  52. package/dist/{manifest-ByE6YPG0.js → manifest-BGKxmKLy.mjs} +14 -19
  53. package/dist/manifest-BGKxmKLy.mjs.map +1 -0
  54. package/dist/metrics-BaEX__MN.mjs +352 -0
  55. package/dist/metrics-BaEX__MN.mjs.map +1 -0
  56. package/dist/metrics-CVXFL7YT.d.mts +64 -0
  57. package/dist/metrics.d.mts +2 -0
  58. package/dist/metrics.mjs +2 -0
  59. package/dist/{chunk-Bp6m_JJh.js → rolldown-runtime-D7D4PA-g.mjs} +4 -4
  60. package/dist/runtime-config/index.d.mts +2 -0
  61. package/dist/runtime-config/index.mjs +3 -0
  62. package/dist/runtime-config-Oa55gAew.mjs +97 -0
  63. package/dist/runtime-config-Oa55gAew.mjs.map +1 -0
  64. package/dist/{server-CXTQ7odl.js → server-CMnxz3h0.mjs} +21 -60
  65. package/dist/server-CMnxz3h0.mjs.map +1 -0
  66. package/dist/service-DLkhuxYl.d.mts +27 -0
  67. package/dist/service-jWxxfEht.mjs +7 -0
  68. package/dist/service-jWxxfEht.mjs.map +1 -0
  69. package/dist/state-store/index.d.mts +2 -0
  70. package/dist/state-store/index.mjs +2 -0
  71. package/dist/{state-store-yl6LiTQ0.js → state-store-uFvHY7Ax.mjs} +15 -22
  72. package/dist/state-store-uFvHY7Ax.mjs.map +1 -0
  73. package/dist/status/{index.d.ts → index.d.mts} +1 -4
  74. package/dist/status/{index.js → index.mjs} +2 -6
  75. package/dist/{status-B-oZBc33.js → status-CKb9IhQ9.mjs} +14 -16
  76. package/dist/status-CKb9IhQ9.mjs.map +1 -0
  77. package/dist/table-V0tgUC5i.mjs +370 -0
  78. package/dist/table-V0tgUC5i.mjs.map +1 -0
  79. package/dist/types-xZtSmrGA.d.mts +220 -0
  80. package/dist/webhook/index.d.mts +3 -0
  81. package/dist/webhook/index.mjs +12 -0
  82. package/dist/webhook/index.mjs.map +1 -0
  83. package/dist/wings-I56hGtNv.mjs +325 -0
  84. package/dist/wings-I56hGtNv.mjs.map +1 -0
  85. package/package.json +64 -51
  86. package/src/catalog/table.ts +201 -0
  87. package/src/connector-app/create-table.ts +47 -0
  88. package/src/connector-app/demo.ts +42 -0
  89. package/src/connector-app/index.ts +2 -0
  90. package/src/connector-app/start.ts +1 -1
  91. package/src/core/builder.ts +15 -23
  92. package/src/core/index.ts +11 -1
  93. package/src/core/types.ts +114 -39
  94. package/src/demo/definition.ts +68 -0
  95. package/src/demo/generate.ts +167 -0
  96. package/src/demo/index.ts +3 -0
  97. package/src/demo/run.ts +142 -0
  98. package/src/iceberg/annotations.ts +62 -0
  99. package/src/iceberg/error.ts +9 -0
  100. package/src/iceberg/index.ts +3 -0
  101. package/src/iceberg/table.ts +511 -0
  102. package/src/index.ts +3 -1
  103. package/src/ingestion/engine.ts +240 -60
  104. package/src/ingestor/arrow.ts +248 -0
  105. package/src/ingestor/console.ts +13 -0
  106. package/src/ingestor/index.ts +9 -0
  107. package/src/ingestor/instrumented.ts +61 -0
  108. package/src/ingestor/service.ts +30 -0
  109. package/src/ingestor/wings.ts +143 -0
  110. package/src/manifest/config.ts +3 -3
  111. package/src/metrics.ts +125 -33
  112. package/src/runtime-config/config.ts +14 -0
  113. package/src/runtime-config/constants.ts +5 -2
  114. package/src/runtime-config/error.ts +4 -1
  115. package/src/runtime-config/index.ts +2 -0
  116. package/src/runtime-config/layer.ts +1 -1
  117. package/src/runtime-config/table-bindings.ts +92 -0
  118. package/src/state-store/layer-key-value-store.ts +8 -3
  119. package/src/state-store/layer-memory.ts +1 -1
  120. package/src/state-store/layer-sql.ts +4 -4
  121. package/src/state-store/schema.ts +2 -2
  122. package/src/state-store/state.ts +14 -2
  123. package/src/status/route.ts +2 -2
  124. package/src/telemetry.ts +25 -10
  125. package/src/webhook/server.ts +39 -40
  126. package/dist/auth/index.d.ts +0 -2
  127. package/dist/auth/index.js +0 -3
  128. package/dist/auth-DvU_CZ7C.js.map +0 -1
  129. package/dist/connector-app/index.d.ts +0 -14
  130. package/dist/connector-app/index.js +0 -11
  131. package/dist/connector-app-d7Z-SZLQ.js +0 -64
  132. package/dist/connector-app-d7Z-SZLQ.js.map +0 -1
  133. package/dist/constants-BRhIX_rz.js.map +0 -1
  134. package/dist/errors/index.d.ts +0 -2
  135. package/dist/errors/index.js +0 -3
  136. package/dist/errors-DHWylqRZ.js.map +0 -1
  137. package/dist/index-Byr0Lf0C.d.ts +0 -25
  138. package/dist/index-o1-Z3n7V.d.ts +0 -55
  139. package/dist/index.d.ts +0 -14
  140. package/dist/index.js +0 -58
  141. package/dist/index.js.map +0 -1
  142. package/dist/ingestion/index.d.ts +0 -6
  143. package/dist/ingestion/index.js +0 -10
  144. package/dist/ingestion-BQo4cbGw.js +0 -200
  145. package/dist/ingestion-BQo4cbGw.js.map +0 -1
  146. package/dist/manifest/index.d.ts +0 -2
  147. package/dist/manifest-ByE6YPG0.js.map +0 -1
  148. package/dist/metrics-CVAk1ALR.d.ts +0 -53
  149. package/dist/metrics-CWPy2Aqc.js +0 -96
  150. package/dist/metrics-CWPy2Aqc.js.map +0 -1
  151. package/dist/metrics.d.ts +0 -4
  152. package/dist/metrics.js +0 -3
  153. package/dist/publisher/index.d.ts +0 -5
  154. package/dist/publisher/index.js +0 -6
  155. package/dist/publisher-BYT3RLVO.js +0 -131
  156. package/dist/publisher-BYT3RLVO.js.map +0 -1
  157. package/dist/runtime-config/index.d.ts +0 -2
  158. package/dist/runtime-config/index.js +0 -4
  159. package/dist/runtime-config-BpB-d_bF.js +0 -51
  160. package/dist/runtime-config-BpB-d_bF.js.map +0 -1
  161. package/dist/server-CXTQ7odl.js.map +0 -1
  162. package/dist/service-DuFiQwid.js +0 -191
  163. package/dist/service-DuFiQwid.js.map +0 -1
  164. package/dist/service-IE5qaf9x.d.ts +0 -32
  165. package/dist/state-store/index.d.ts +0 -3
  166. package/dist/state-store/index.js +0 -5
  167. package/dist/state-store-yl6LiTQ0.js.map +0 -1
  168. package/dist/status-B-oZBc33.js.map +0 -1
  169. package/dist/types-B35J5YPu.d.ts +0 -174
  170. package/dist/webhook/index.d.ts +0 -6
  171. package/dist/webhook/index.js +0 -8
  172. package/dist/webhook-DI-Afxkg.js +0 -13
  173. package/dist/webhook-DI-Afxkg.js.map +0 -1
  174. package/src/publisher/console.ts +0 -18
  175. package/src/publisher/index.ts +0 -7
  176. package/src/publisher/instrumented.ts +0 -68
  177. package/src/publisher/service.ts +0 -37
  178. package/src/publisher/wings.ts +0 -204
@@ -0,0 +1,73 @@
1
+ import { E as TableSource } from "./types-xZtSmrGA.mjs";
2
+ import { Config, Effect, FileSystem } from "effect";
3
+ import { TableIdentifier } from "iceberg-js";
4
+ //#region src/runtime-config/error.d.ts
5
+ type RuntimeConfigErrorCode = "CONFIG_PATH_MISSING" | "CONFIG_FILE_UNREADABLE" | "CONFIG_JSON_INVALID" | "TABLE_BINDINGS_MISSING" | "TABLE_BINDINGS_INVALID" | "TABLE_BINDINGS_MISMATCH";
6
+ declare const RuntimeConfigError_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 & {
7
+ readonly _tag: "RuntimeConfigError";
8
+ } & Readonly<A>;
9
+ /** Expected hosted-config failure with a stable code and diagnostic cause. */
10
+ declare class RuntimeConfigError extends RuntimeConfigError_base<{
11
+ readonly code: RuntimeConfigErrorCode;
12
+ readonly message: string;
13
+ readonly cause: Error;
14
+ }> {}
15
+ //#endregion
16
+ //#region src/runtime-config/config.d.ts
17
+ /** Shared HTTP port used by hosted and sandbox connector entrypoints. */
18
+ declare const httpPort: Config.Config<number>;
19
+ /** Wings URL, including the protocol. */
20
+ declare const wingsUri: Config.Config<URL>;
21
+ /** Wings catalog ID. */
22
+ declare const catalog: Config.Config<string>;
23
+ //#endregion
24
+ //#region src/runtime-config/constants.d.ts
25
+ /** Shared runtime keys owned by Airfoil rather than an individual connector. */
26
+ declare const PlatformRuntimeKey: {
27
+ readonly configPath: "AIRFOIL_CONFIG_PATH";
28
+ readonly httpPort: "AIRFOIL_HTTP_PORT";
29
+ readonly tableBindings: "AIRFOIL_TABLE_BINDINGS";
30
+ readonly connectorInstanceId: "AIRFOIL_CONNECTOR_INSTANCE_ID";
31
+ readonly stateTable: "AIRFOIL_STATE_TABLE";
32
+ readonly postgresConnectionString: "POSTGRES_CONNECTION_STRING";
33
+ readonly wingsUri: "WINGS_URI";
34
+ readonly catalog: "AIRFOIL_CATALOG";
35
+ readonly otelEnabled: "OTEL_ENABLED";
36
+ readonly otelExporterOtlpEndpoint: "OTEL_EXPORTER_OTLP_ENDPOINT";
37
+ readonly otelExporterOtlpHeaders: "OTEL_EXPORTER_OTLP_HEADERS";
38
+ readonly otelServiceName: "OTEL_SERVICE_NAME";
39
+ readonly otelServiceVersion: "OTEL_SERVICE_VERSION";
40
+ readonly otelResourceAttributes: "OTEL_RESOURCE_ATTRIBUTES";
41
+ };
42
+ /** Defaults for optional platform-owned runtime configuration. */
43
+ declare const PlatformRuntimeDefault: {
44
+ readonly httpPort: 8080;
45
+ readonly stateTable: "_airfoil_connectors_state";
46
+ };
47
+ //#endregion
48
+ //#region src/runtime-config/layer.d.ts
49
+ /**
50
+ * Loads the required JSON file and lets environment values override it per key.
51
+ * Connector field validation remains in the connector's Effect Config.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * program.pipe(Effect.provide(layerHosted()));
56
+ * ```
57
+ */
58
+ declare const layerHosted: () => import("effect/Layer").Layer<never, RuntimeConfigError, FileSystem.FileSystem>;
59
+ //#endregion
60
+ //#region src/runtime-config/table-bindings.d.ts
61
+ /** An Iceberg table and its storage location for each connector resource. */
62
+ type TableBinding = TableIdentifier & {
63
+ readonly location?: string | undefined;
64
+ };
65
+ type ResolvedTableBindings<Source extends TableSource> = Readonly<Partial<Record<Source["resources"][number]["name"], TableBinding>>>;
66
+ /** 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>;
68
+ declare namespace index_d_exports {
69
+ export { PlatformRuntimeDefault, PlatformRuntimeKey, ResolvedTableBindings, RuntimeConfigError, RuntimeConfigErrorCode, TableBinding, catalog, httpPort, layerHosted, loadTableBindings, wingsUri };
70
+ }
71
+ //#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
@@ -0,0 +1,16 @@
1
+ import { t as index_d_exports } from "./index-BX8G7d41.mjs";
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";
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";
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";
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 ADDED
@@ -0,0 +1,45 @@
1
+ import { t as ConnectorError } from "./errors-pT0YVJU5.mjs";
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";
13
+ import { t as webhook_exports } from "./webhook/index.mjs";
14
+ import { DateTime, Effect, Option } from "effect";
15
+ //#region src/core/builder.ts
16
+ const Connector = { define: (definition) => definition };
17
+ const Resource = { entity: (definition) => definition };
18
+ const Fetch = {
19
+ page: (definition) => definition,
20
+ changes: (definition) => definition,
21
+ feed: (definition) => definition
22
+ };
23
+ const decodeFailure = (kind, value) => new ConnectorError({ message: `Invalid ${kind} cursor value: ${String(value)}` });
24
+ const Cursor = {
25
+ string: () => ({
26
+ kind: "string",
27
+ decode: (value) => typeof value === "string" ? Effect.succeed(value) : Effect.fail(decodeFailure("string", value))
28
+ }),
29
+ number: () => ({
30
+ kind: "number",
31
+ decode: (value) => typeof value === "number" && Number.isFinite(value) ? Effect.succeed(value) : Effect.fail(decodeFailure("number", value))
32
+ }),
33
+ isoDateTime: () => ({
34
+ kind: "isoDateTime",
35
+ decode: (value) => {
36
+ if (typeof value !== "string" || Option.isNone(DateTime.make(value))) return Effect.fail(decodeFailure("ISO datetime", value));
37
+ return Effect.succeed(value);
38
+ }
39
+ }),
40
+ nowIsoDateTime: Effect.map(DateTime.now, DateTime.formatIso)
41
+ };
42
+ //#endregion
43
+ export { auth_exports as Auth, Connector, connector_app_exports as ConnectorApp, ConnectorError, Cursor, demo_exports as Demo, Fetch, iceberg_exports as Iceberg, ingestion_exports as Ingestion, ingestor_exports as Ingestor, manifest_exports as Manifest, metrics_exports as Metrics, Resource, runtime_config_exports as RuntimeConfig, state_store_exports as StateStore, status_exports as Status, telemetry_exports as Telemetry, webhook_exports as Webhook };
44
+
45
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/core/builder.ts"],"sourcesContent":["import { DateTime, Effect, Option } from \"effect\";\n\nimport type {\n ChangesFeed,\n ChangesFetch,\n ConnectorDefinition,\n Cursor as CursorType,\n PageFetch,\n ResourceDefinition,\n ResourceRequiredField,\n ResourceSchema,\n} from \"./types\";\n\nimport { ConnectorError } from \"../errors\";\n\nexport const Connector = {\n define: <\n const Resources extends ReadonlyArray<ResourceDefinition>,\n const FeedResources extends ReadonlyArray<Resources[number]> = Resources,\n >(\n definition: ConnectorDefinition<Resources, FeedResources>,\n ) => definition,\n};\n\nexport const Resource = {\n entity: <\n S extends ResourceSchema,\n Payload = never,\n R = never,\n const Name extends string = string,\n const Version extends ResourceRequiredField<S> = ResourceRequiredField<S>,\n >(\n definition: ResourceDefinition<S, Payload, R, Name, Version>,\n ): ResourceDefinition<S, Payload, R, Name, Version> => definition,\n};\n\nexport const Fetch = {\n page: <Row extends object = never, R = never>(definition: PageFetch<Row, R>) => definition,\n changes: <Row extends object = never, R = never>(definition: ChangesFetch<Row, R>) => definition,\n feed: <const Resources extends ReadonlyArray<ResourceDefinition>, R = never>(\n definition: ChangesFeed<Resources, R>,\n ) => definition,\n};\n\nconst decodeFailure = (kind: string, value: unknown) =>\n new ConnectorError({ message: `Invalid ${kind} cursor value: ${String(value)}` });\n\nexport const Cursor = {\n string: (): CursorType.Definition<string> => ({\n kind: \"string\",\n decode: (value) =>\n typeof value === \"string\"\n ? Effect.succeed(value)\n : Effect.fail(decodeFailure(\"string\", value)),\n }),\n\n number: (): CursorType.Definition<number> => ({\n kind: \"number\",\n decode: (value) =>\n typeof value === \"number\" && Number.isFinite(value)\n ? Effect.succeed(value)\n : Effect.fail(decodeFailure(\"number\", value)),\n }),\n\n isoDateTime: (): CursorType.Definition<string> => ({\n kind: \"isoDateTime\",\n decode: (value) => {\n if (typeof value !== \"string\" || Option.isNone(DateTime.make(value))) {\n return Effect.fail(decodeFailure(\"ISO datetime\", value));\n }\n return Effect.succeed(value);\n },\n }),\n\n nowIsoDateTime: Effect.map(DateTime.now, DateTime.formatIso),\n};\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAa,YAAY,EACvB,SAIE,eACG,WACP;AAEA,MAAa,WAAW,EACtB,SAOE,eACqD,WACzD;AAEA,MAAa,QAAQ;CACnB,OAA8C,eAAkC;CAChF,UAAiD,eAAqC;CACtF,OACE,eACG;AACP;AAEA,MAAM,iBAAiB,MAAc,UACnC,IAAI,eAAe,EAAE,SAAS,WAAW,KAAK,iBAAiB,OAAO,KAAK,IAAI,CAAC;AAElF,MAAa,SAAS;CACpB,eAA8C;EAC5C,MAAM;EACN,SAAS,UACP,OAAO,UAAU,WACb,OAAO,QAAQ,KAAK,IACpB,OAAO,KAAK,cAAc,UAAU,KAAK,CAAC;CAClD;CAEA,eAA8C;EAC5C,MAAM;EACN,SAAS,UACP,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAC9C,OAAO,QAAQ,KAAK,IACpB,OAAO,KAAK,cAAc,UAAU,KAAK,CAAC;CAClD;CAEA,oBAAmD;EACjD,MAAM;EACN,SAAS,UAAU;GACjB,IAAI,OAAO,UAAU,YAAY,OAAO,OAAO,SAAS,KAAK,KAAK,CAAC,GACjE,OAAO,OAAO,KAAK,cAAc,gBAAgB,KAAK,CAAC;GAEzD,OAAO,OAAO,QAAQ,KAAK;EAC7B;CACF;CAEA,gBAAgB,OAAO,IAAI,SAAS,KAAK,SAAS,SAAS;AAC7D"}
@@ -0,0 +1,2 @@
1
+ import { n as RunOptions, r as run } from "../index-BfXpgxk9.mjs";
2
+ export { type RunOptions, run };
@@ -0,0 +1,2 @@
1
+ import { n as run } from "../ingestion-q0WwqUSt.mjs";
2
+ export { run };
@@ -0,0 +1,275 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
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";
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";
9
+ import { Array, DateTime, Effect, Layer, Order, Queue } from "effect";
10
+ import { HttpRouter, HttpServerResponse } from "effect/http";
11
+ import * as Observability from "effect/observability";
12
+ //#region src/ingestion/engine.ts
13
+ function run(definition, options) {
14
+ return Effect.gen(function* () {
15
+ if (definition.changes) yield* validateFeed(definition, definition.changes);
16
+ const ingestor = yield* Ingestor;
17
+ const connector = selectResources(definition, ingestor.resourceNames);
18
+ const queueLayer = makeWebhookQueueLayer(connector.name);
19
+ const runtimeLayer = options?.webhook ? Layer.mergeAll(queueLayer, makeWebhookServerLayer(connector, options.webhook).pipe(Layer.provide(queueLayer))) : Layer.empty;
20
+ return yield* Effect.gen(function* () {
21
+ const initialCutoff = options?.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));
22
+ yield* Effect.logInfo("Connector started").pipe(Effect.annotateLogs({
23
+ [Attr.connectorName]: connector.name,
24
+ resources: connector.resources.length
25
+ }));
26
+ const sourceRun = runIngestion(connector, initialCutoff);
27
+ const webhookRun = options?.webhook ? runWebhookRuntime(connector, options.webhook.routes) : Effect.void;
28
+ return yield* Effect.all([sourceRun, webhookRun], { concurrency: "unbounded" }).pipe(Effect.asVoid);
29
+ }).pipe(Effect.provide(runtimeLayer));
30
+ });
31
+ }
32
+ const selectResources = (connector, names) => {
33
+ if (names === void 0) return connector;
34
+ const isSelected = (resource) => names.includes(resource.name);
35
+ const { changes, ...rest } = connector;
36
+ const feedResources = changes?.resources.filter(isSelected) ?? [];
37
+ return {
38
+ ...rest,
39
+ resources: connector.resources.filter(isSelected),
40
+ ...changes && feedResources.length > 0 ? { changes: {
41
+ ...changes,
42
+ resources: feedResources
43
+ } } : {}
44
+ };
45
+ };
46
+ const makeWebhookQueueLayer = (connector) => Layer.effect(WebhookQueue)(Effect.gen(function* () {
47
+ const queue = yield* Queue.bounded(1024);
48
+ yield* setWebhookQueueDepth(connector, 0);
49
+ return WebhookQueue.of({ queue });
50
+ }));
51
+ const runWebhookRuntime = (connector, routes) => {
52
+ const hasAfterEnqueue = routes.some((route) => route.ackMode === "after-enqueue");
53
+ return Effect.all([hasAfterEnqueue ? runWebhookQueueConsumer(connector) : Effect.void, Effect.never], { concurrency: "unbounded" }).pipe(Effect.asVoid);
54
+ };
55
+ const runWebhookQueueConsumer = (connector) => Effect.gen(function* () {
56
+ const queue = yield* WebhookQueue;
57
+ while (true) {
58
+ const batch = yield* Queue.take(queue.queue);
59
+ const depth = yield* Queue.size(queue.queue);
60
+ yield* setWebhookQueueDepth(connector.name, depth);
61
+ yield* ingestBatch({
62
+ connector: connector.name,
63
+ resource: batch.resource,
64
+ source: "webhook",
65
+ batch: batch.batch
66
+ });
67
+ }
68
+ });
69
+ const makeWebhookServerLayer = (connector, options) => {
70
+ const healthPath = options.healthPath ?? "/health";
71
+ const metricsPath = options.metricsPath === void 0 ? "/metrics" : options.metricsPath;
72
+ const statusPath = options.statusPath === void 0 ? "/status" : options.statusPath;
73
+ const app = Layer.mergeAll(router(options.routes, {
74
+ connectorName: connector.name,
75
+ resourceNames: connector.resources.map((resource) => resource.name)
76
+ }), HttpRouter.add("GET", healthPath, Effect.succeed(HttpServerResponse.text("ok"))), ...metricsPath === false ? [] : [Observability.PrometheusMetrics.layerHttp({ path: metricsPath })], ...statusPath === false ? [] : [statusRoute(connector, statusPath)]);
77
+ return HttpRouter.serve(app, { disableLogger: options.disableHttpLogger ?? true });
78
+ };
79
+ const runIngestion = (connector, initialCutoff) => Effect.gen(function* () {
80
+ const feed = connector.changes;
81
+ yield* Effect.all([Effect.forEach(connector.resources, (resource) => runResourceSources(connector, resource, initialCutoff), { concurrency: "unbounded" }), feed ? runChangesFeed(connector, feed, initialCutoff) : Effect.void], { concurrency: "unbounded" });
82
+ });
83
+ const bySavedAt = Order.mapInput(Order.String, (state) => state.lastSuccessAt ?? "");
84
+ const validateFeed = (connector, feed) => Effect.forEach(feed.resources, (member, index) => {
85
+ if (feed.resources.findIndex((item) => item.name === member.name) !== index) return Effect.fail(new ConnectorError({ message: `Resource ${member.name} is in the changes feed twice` }));
86
+ const resource = connector.resources.find((item) => item.name === member.name);
87
+ if (!resource) return Effect.fail(new ConnectorError({ message: `Changes feed resource ${member.name} is not a resource of connector ${connector.name}` }));
88
+ if (resource.changes) return Effect.fail(new ConnectorError({ message: `Resource ${member.name} has its own changes and is also in the changes feed` }));
89
+ return Effect.void;
90
+ }).pipe(Effect.andThen(feed.resources.length === 0 ? Effect.fail(new ConnectorError({ message: "The changes feed has no resources" })) : Effect.void));
91
+ const initializeResourceState = (existing, initialCutoff) => ({
92
+ ...existing,
93
+ changes: existing?.changes ?? { cursor: initialCutoff },
94
+ backfill: existing?.backfill ?? {
95
+ cutoff: initialCutoff,
96
+ completed: false
97
+ }
98
+ });
99
+ const getInitializedState = Effect.fnUntraced(function* (resource, initialCutoff) {
100
+ const existing = yield* (yield* StateStore).getResourceState(resource);
101
+ return initializeResourceState(existing, initialCutoff);
102
+ });
103
+ const runResourceSources = (connector, resource, initialCutoff) => {
104
+ const runs = [resource.backfill ? isolateSourceFailure(runBackfill(connector, resource, initialCutoff), connector, resource, "backfill") : Effect.void, resource.changes ? isolateSourceFailure(runChanges(connector, resource, initialCutoff), connector, resource, "changes") : Effect.void];
105
+ return initializeRuntimeStatus(connector, resource, initialCutoff).pipe(Effect.andThen(Effect.all(runs, { concurrency: "unbounded" })), Effect.asVoid, Effect.catch((error) => setSyncState({
106
+ connector: connector.name,
107
+ resource: resource.name
108
+ }, "error").pipe(Effect.andThen(Effect.logError("Connector resource initialization failed", error)), Effect.annotateLogs({
109
+ [Attr.connectorName]: connector.name,
110
+ resource: resource.name
111
+ }), Effect.andThen(Effect.never))));
112
+ };
113
+ const recordResourceError = (connector, resource, source, operation) => (effect) => effect.pipe(Effect.tapError(() => setSyncState({
114
+ connector: connector.name,
115
+ resource: resource.name
116
+ }, "error").pipe(Effect.andThen(StateStore.pipe(Effect.flatMap((store) => store.setResourceError(resource.name, source, operation)))))));
117
+ const isolateSourceFailure = (effect, connector, resource, source) => effect.pipe(Effect.catch((error) => Effect.logError("Connector source parked", error).pipe(Effect.annotateLogs({
118
+ [Attr.connectorName]: connector.name,
119
+ resource: resource.name,
120
+ source
121
+ }), Effect.andThen(Effect.never))));
122
+ const refreshRuntimeStatus = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
123
+ const state = yield* getInitializedState(resource.name, initialCutoff);
124
+ yield* setSyncState({
125
+ connector: connector.name,
126
+ resource: resource.name
127
+ }, deriveSyncState(connector, resource, state));
128
+ return state;
129
+ });
130
+ const initializeRuntimeStatus = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
131
+ const state = yield* getInitializedState(resource.name, initialCutoff);
132
+ yield* setSyncState({
133
+ connector: connector.name,
134
+ resource: resource.name
135
+ }, deriveSyncState(connector, resource, state));
136
+ if (resource.backfill) yield* setLastSuccessTimestamp({
137
+ connector: connector.name,
138
+ resource: resource.name,
139
+ source: "backfill"
140
+ }, state.backfill?.lastSuccessAt);
141
+ if (hasChanges(connector, resource)) yield* setLastSuccessTimestamp({
142
+ connector: connector.name,
143
+ resource: resource.name,
144
+ source: "changes"
145
+ }, state.changes?.lastSuccessAt);
146
+ });
147
+ const runBackfill = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
148
+ if (!resource.backfill) return;
149
+ const store = yield* StateStore;
150
+ let state = yield* getInitializedState(resource.name, initialCutoff);
151
+ if (state.backfill?.completed === true) {
152
+ yield* store.clearResourceError(resource.name, "backfill").pipe(recordResourceError(connector, resource, "backfill", "checkpoint"));
153
+ yield* refreshRuntimeStatus(connector, resource, initialCutoff);
154
+ return;
155
+ }
156
+ while (state.backfill?.completed !== true) {
157
+ const backfill = state.backfill ?? {
158
+ cutoff: initialCutoff,
159
+ completed: false
160
+ };
161
+ const clearsVisibleError = state.lastError?.source === "backfill";
162
+ const page = yield* resource.backfill.fetch({
163
+ pageCursor: backfill.pageCursor,
164
+ cutoff: backfill.cutoff
165
+ }).pipe(recordResourceError(connector, resource, "backfill", "fetch"));
166
+ yield* ingestBatch({
167
+ connector: connector.name,
168
+ resource: resource.name,
169
+ source: "backfill",
170
+ batch: {
171
+ cursor: page.nextPageCursor ?? backfill.cutoff,
172
+ rows: page.rows
173
+ }
174
+ }).pipe(recordResourceError(connector, resource, "backfill", "ingest"));
175
+ const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
176
+ state = {
177
+ ...state,
178
+ backfill: {
179
+ cutoff: backfill.cutoff,
180
+ pageCursor: page.nextPageCursor,
181
+ completed: !page.hasMore,
182
+ lastSuccessAt
183
+ }
184
+ };
185
+ yield* Effect.withSpan(store.setBackfillState(resource.name, {
186
+ cutoff: normalizeCursor(backfill.cutoff),
187
+ pageCursor: page.nextPageCursor === void 0 ? void 0 : normalizeCursor(page.nextPageCursor),
188
+ completed: !page.hasMore,
189
+ lastSuccessAt
190
+ }).pipe(Effect.andThen(setLastSuccessTimestamp({
191
+ connector: connector.name,
192
+ resource: resource.name,
193
+ source: "backfill"
194
+ }, lastSuccessAt)), Effect.andThen(store.clearResourceError(resource.name, "backfill")), Effect.tapError((error) => annotateError("state_set", error))), SpanName.stateSet, { attributes: { [Attr.stateKey]: resource.name } }).pipe(recordResourceError(connector, resource, "backfill", "checkpoint"));
195
+ if (clearsVisibleError || !page.hasMore) state = yield* refreshRuntimeStatus(connector, resource, initialCutoff);
196
+ }
197
+ });
198
+ const runChanges = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
199
+ if (!resource.changes) return;
200
+ const store = yield* StateStore;
201
+ while (true) {
202
+ const state = yield* getInitializedState(resource.name, initialCutoff);
203
+ const cursor = state.changes?.cursor ?? initialCutoff;
204
+ const clearsVisibleError = state.lastError?.source === "changes";
205
+ const page = yield* resource.changes.fetch({ cursor }).pipe(recordResourceError(connector, resource, "changes", "fetch"));
206
+ yield* ingestBatch({
207
+ connector: connector.name,
208
+ resource: resource.name,
209
+ source: "changes",
210
+ batch: {
211
+ cursor: page.cursor,
212
+ rows: page.rows
213
+ }
214
+ }).pipe(recordResourceError(connector, resource, "changes", "ingest"));
215
+ const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
216
+ yield* Effect.withSpan(store.setChangesState(resource.name, {
217
+ cursor: normalizeCursor(page.cursor),
218
+ lastSuccessAt
219
+ }).pipe(Effect.andThen(setLastSuccessTimestamp({
220
+ connector: connector.name,
221
+ resource: resource.name,
222
+ source: "changes"
223
+ }, lastSuccessAt)), Effect.andThen(store.clearResourceError(resource.name, "changes")), Effect.tapError((error) => annotateError("state_set", error))), SpanName.stateSet, { attributes: { [Attr.stateKey]: resource.name } }).pipe(recordResourceError(connector, resource, "changes", "checkpoint"));
224
+ if (clearsVisibleError) yield* refreshRuntimeStatus(connector, resource, initialCutoff);
225
+ if (!page.hasMore) yield* Effect.sleep(resource.changes.interval ?? "1 minute");
226
+ }
227
+ });
228
+ const runChangesFeed = (connector, feed, initialCutoff) => Effect.gen(function* () {
229
+ const store = yield* StateStore;
230
+ const members = feed.resources;
231
+ const selected = new Set(members.map((resource) => resource.name));
232
+ const recordFeedError = (operation) => (effect) => effect.pipe(Effect.tapError(() => Effect.forEach(members, (resource) => setSyncState({
233
+ connector: connector.name,
234
+ resource: resource.name
235
+ }, "error").pipe(Effect.andThen(store.setResourceError(resource.name, "changes", operation))), { discard: true })));
236
+ while (true) {
237
+ const states = yield* Effect.forEach(members, (resource) => store.getResourceState(resource.name));
238
+ const saved = states.flatMap((state) => state?.changes ? [state.changes] : []);
239
+ const cursor = Array.isReadonlyArrayNonEmpty(saved) ? Array.min(saved, bySavedAt).cursor : initialCutoff;
240
+ const result = yield* feed.fetch({
241
+ cursor,
242
+ selected
243
+ }).pipe(recordFeedError("fetch"));
244
+ yield* Effect.forEach(members, (resource) => ingestBatch({
245
+ connector: connector.name,
246
+ resource: resource.name,
247
+ source: "changes",
248
+ batch: {
249
+ cursor: result.cursor,
250
+ rows: result.rows[resource.name] ?? []
251
+ }
252
+ }), { discard: true }).pipe(recordFeedError("ingest"));
253
+ const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
254
+ yield* Effect.forEach(members, (resource) => Effect.withSpan(store.setChangesState(resource.name, {
255
+ cursor: normalizeCursor(result.cursor),
256
+ lastSuccessAt
257
+ }).pipe(Effect.andThen(setLastSuccessTimestamp({
258
+ connector: connector.name,
259
+ resource: resource.name,
260
+ source: "changes"
261
+ }, lastSuccessAt)), Effect.andThen(store.clearResourceError(resource.name, "changes")), Effect.tapError((error) => annotateError("state_set", error))), SpanName.stateSet, { attributes: { [Attr.stateKey]: resource.name } }), { discard: true }).pipe(recordFeedError("checkpoint"));
262
+ yield* Effect.forEach(members, (resource, index) => states[index]?.lastError?.source === "changes" ? refreshRuntimeStatus(connector, resource, initialCutoff) : Effect.void);
263
+ if (!result.hasMore) yield* Effect.sleep(feed.interval ?? "1 minute");
264
+ }
265
+ }).pipe(Effect.catch((error) => Effect.logError("Connector changes feed parked", error).pipe(Effect.annotateLogs({
266
+ [Attr.connectorName]: connector.name,
267
+ resources: feed.resources.map((resource) => resource.name).join(",")
268
+ }), Effect.andThen(Effect.never))));
269
+ //#endregion
270
+ //#region src/ingestion/index.ts
271
+ var ingestion_exports = /* @__PURE__ */ __exportAll({ run: () => run });
272
+ //#endregion
273
+ export { run as n, ingestion_exports as t };
274
+
275
+ //# sourceMappingURL=ingestion-q0WwqUSt.mjs.map
@@ -0,0 +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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"}
@@ -0,0 +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 };
@@ -0,0 +1,4 @@
1
+ import { n as layerWingsConfig, t as layerWings } from "../wings-I56hGtNv.mjs";
2
+ import { t as Ingestor } from "../service-jWxxfEht.mjs";
3
+ import { n as layerConsole } from "../ingestor-D4L-HPkg.mjs";
4
+ export { Ingestor, layerConsole, layerWings, layerWingsConfig };
@@ -0,0 +1,26 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { n as layerWingsConfig, t as layerWings } from "./wings-I56hGtNv.mjs";
3
+ import { t as Ingestor } from "./service-jWxxfEht.mjs";
4
+ import { Effect, Layer } from "effect";
5
+ //#region src/ingestor/console.ts
6
+ /** Logs batches without sending them to Wings. */
7
+ const layerConsole = Layer.succeed(Ingestor)({ ingest: ({ resource, source, batch }) => Effect.logInfo(`[ingestor] -> Source: ${source} | Resource: ${resource}`).pipe(Effect.annotateLogs({
8
+ rows: batch.rows.length,
9
+ cursor: batch.cursor,
10
+ source
11
+ }), Effect.as({
12
+ rows: batch.rows.length,
13
+ bytes: 0
14
+ })) });
15
+ //#endregion
16
+ //#region src/ingestor/index.ts
17
+ var ingestor_exports = /* @__PURE__ */ __exportAll({
18
+ Ingestor: () => Ingestor,
19
+ layerConsole: () => layerConsole,
20
+ layerWings: () => layerWings,
21
+ layerWingsConfig: () => layerWingsConfig
22
+ });
23
+ //#endregion
24
+ export { layerConsole as n, ingestor_exports as t };
25
+
26
+ //# sourceMappingURL=ingestor-D4L-HPkg.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingestor-D4L-HPkg.mjs","names":[],"sources":["../src/ingestor/console.ts","../src/ingestor/index.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\n\nimport { Ingestor } from \"./service\";\n\n/** Logs batches without sending them to Wings. */\nexport const layerConsole = Layer.succeed(Ingestor)({\n ingest: ({ resource, source, batch }) =>\n Effect.logInfo(`[ingestor] -> Source: ${source} | Resource: ${resource}`).pipe(\n Effect.annotateLogs({ rows: batch.rows.length, cursor: batch.cursor, source }),\n // Nothing is encoded, so there are no bytes to count.\n Effect.as({ rows: batch.rows.length, bytes: 0 }),\n ),\n});\n","export { layerConsole } from \"./console\";\nexport {\n Ingestor,\n type IngestOptions,\n type IngestorService,\n type IngestResult,\n type IngestSource,\n} from \"./service\";\nexport { layerWings, layerWingsConfig, type WingsIngestorConfig } from \"./wings\";\n"],"mappings":";;;;;;AAKA,MAAa,eAAe,MAAM,QAAQ,QAAQ,CAAC,CAAC,EAClD,SAAS,EAAE,UAAU,QAAQ,YAC3B,OAAO,QAAQ,yBAAyB,OAAO,eAAe,UAAU,CAAC,CAAC,KACxE,OAAO,aAAa;CAAE,MAAM,MAAM,KAAK;CAAQ,QAAQ,MAAM;CAAQ;AAAO,CAAC,GAE7E,OAAO,GAAG;CAAE,MAAM,MAAM,KAAK;CAAQ,OAAO;AAAE,CAAC,CACjD,EACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { S as addCurrentSpanEvent, _ as withResourceAttributes, b as EventName, i as ingestDuration, n as batchSize, r as batches, u as rowsIngested, v as Attr, x as SpanName, y as EventAttr } from "./metrics-BaEX__MN.mjs";
2
+ import { t as Ingestor } from "./service-jWxxfEht.mjs";
3
+ import { Effect, Metric } from "effect";
4
+ //#region src/ingestor/instrumented.ts
5
+ const ingestBatch = Effect.fnUntraced(function* (options) {
6
+ const metricAttributes = withResourceAttributes({
7
+ connector: options.connector ?? "unknown",
8
+ resource: options.resource,
9
+ source: options.source
10
+ });
11
+ const batchOutcome = (outcome) => Metric.withAttributes(batches, {
12
+ ...metricAttributes,
13
+ [Attr.batchOutcome]: outcome
14
+ });
15
+ const ingest = (yield* Ingestor).ingest(options).pipe(Effect.tap(() => Effect.annotateCurrentSpan({ [Attr.ingestionSuccess]: true })), Effect.tapError(() => Effect.annotateCurrentSpan({
16
+ [Attr.ingestionSuccess]: false,
17
+ [Attr.errorPhase]: "ingest"
18
+ })));
19
+ const result = yield* Effect.withSpan(ingest, SpanName.ingest, { kind: "producer" }).pipe(Effect.trackDuration(Metric.withAttributes(ingestDuration, metricAttributes)), Effect.onError(() => Metric.update(batchOutcome("error"), 1)));
20
+ yield* Metric.update(batchOutcome("success"), 1);
21
+ yield* Metric.update(Metric.withAttributes(rowsIngested, metricAttributes), options.batch.rows.length);
22
+ yield* Metric.update(Metric.withAttributes(batchSize, metricAttributes), options.batch.rows.length);
23
+ if (options.batch.cursor !== void 0) yield* addCurrentSpanEvent(EventName.batchCheckpoint, { [EventAttr.batchCursor]: options.batch.cursor });
24
+ return result;
25
+ });
26
+ //#endregion
27
+ export { ingestBatch as t };
28
+
29
+ //# sourceMappingURL=instrumented-Bhp7fyvh.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumented-Bhp7fyvh.mjs","names":["Metrics.withResourceAttributes","Metrics.batches","Metrics.ingestDuration","Metrics.rowsIngested","Metrics.batchSize"],"sources":["../src/ingestor/instrumented.ts"],"sourcesContent":["import { Effect, Metric } from \"effect\";\n\nimport type { ResourceBatch } from \"../core/types\";\n\nimport * as Metrics from \"../metrics\";\nimport { Attr, EventAttr, EventName, SpanName, addCurrentSpanEvent } from \"../telemetry\";\nimport { Ingestor, type IngestSource } from \"./service\";\n\nexport const ingestBatch = Effect.fnUntraced(function* (options: {\n readonly connector?: string;\n readonly resource: string;\n readonly source: IngestSource;\n readonly batch: ResourceBatch;\n}) {\n const metricAttributes = Metrics.withResourceAttributes({\n connector: options.connector ?? \"unknown\",\n resource: options.resource,\n source: options.source,\n });\n const batchOutcome = (outcome: \"success\" | \"error\") =>\n Metric.withAttributes(Metrics.batches, {\n ...metricAttributes,\n [Attr.batchOutcome]: outcome,\n });\n\n const ingestor = yield* Ingestor;\n\n const ingest = ingestor.ingest(options).pipe(\n Effect.tap(() => Effect.annotateCurrentSpan({ [Attr.ingestionSuccess]: true })),\n Effect.tapError(() =>\n Effect.annotateCurrentSpan({\n [Attr.ingestionSuccess]: false,\n [Attr.errorPhase]: \"ingest\",\n }),\n ),\n );\n\n // onError keeps the failure, so the engine still sees it and skips the checkpoint.\n const result = yield* Effect.withSpan(ingest, SpanName.ingest, { kind: \"producer\" }).pipe(\n Effect.trackDuration(Metric.withAttributes(Metrics.ingestDuration, metricAttributes)),\n Effect.onError(() => Metric.update(batchOutcome(\"error\"), 1)),\n );\n\n yield* Metric.update(batchOutcome(\"success\"), 1);\n yield* Metric.update(\n Metric.withAttributes(Metrics.rowsIngested, metricAttributes),\n options.batch.rows.length,\n );\n yield* Metric.update(\n Metric.withAttributes(Metrics.batchSize, metricAttributes),\n options.batch.rows.length,\n );\n\n if (options.batch.cursor !== undefined) {\n yield* addCurrentSpanEvent(EventName.batchCheckpoint, {\n [EventAttr.batchCursor]: options.batch.cursor,\n });\n }\n\n return result;\n});\n"],"mappings":";;;;AAQA,MAAa,cAAc,OAAO,WAAW,WAAW,SAKrD;CACD,MAAM,mBAAmBA,uBAA+B;EACtD,WAAW,QAAQ,aAAa;EAChC,UAAU,QAAQ;EAClB,QAAQ,QAAQ;CAClB,CAAC;CACD,MAAM,gBAAgB,YACpB,OAAO,eAAeC,SAAiB;EACrC,GAAG;GACF,KAAK,eAAe;CACvB,CAAC;CAIH,MAAM,UAAS,OAFS,SAAA,CAEA,OAAO,OAAO,CAAC,CAAC,KACtC,OAAO,UAAU,OAAO,oBAAoB,GAAG,KAAK,mBAAmB,KAAK,CAAC,CAAC,GAC9E,OAAO,eACL,OAAO,oBAAoB;GACxB,KAAK,mBAAmB;GACxB,KAAK,aAAa;CACrB,CAAC,CACH,CACF;CAGA,MAAM,SAAS,OAAO,OAAO,SAAS,QAAQ,SAAS,QAAQ,EAAE,MAAM,WAAW,CAAC,CAAC,CAAC,KACnF,OAAO,cAAc,OAAO,eAAeC,gBAAwB,gBAAgB,CAAC,GACpF,OAAO,cAAc,OAAO,OAAO,aAAa,OAAO,GAAG,CAAC,CAAC,CAC9D;CAEA,OAAO,OAAO,OAAO,aAAa,SAAS,GAAG,CAAC;CAC/C,OAAO,OAAO,OACZ,OAAO,eAAeC,cAAsB,gBAAgB,GAC5D,QAAQ,MAAM,KAAK,MACrB;CACA,OAAO,OAAO,OACZ,OAAO,eAAeC,WAAmB,gBAAgB,GACzD,QAAQ,MAAM,KAAK,MACrB;CAEA,IAAI,QAAQ,MAAM,WAAW,KAAA,GAC3B,OAAO,oBAAoB,UAAU,iBAAiB,GACnD,UAAU,cAAc,QAAQ,MAAM,OACzC,CAAC;CAGH,OAAO;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { _ as number, a as configSchema, b as select, c as ConnectorManifest, d as ConfigField, f as ConfigFieldSpec, g as define$1, h as boolean, i as RuntimeConfigDocument, l as ResourceCapability, m as ConnectorConfigDef, n as ConnectorConfigSchema, o as decodeConfig, p as ConfigValuesOf, r as ConnectorConfigValues, s as toRuntimeDocument, u as define, v as optional, x as string, y as secret } from "../index-eFuoMZZ3.mjs";
2
+ export { type ConfigField, type ConfigFieldSpec, type ConfigValuesOf, type ConnectorConfigDef, type ConnectorConfigSchema, type ConnectorConfigValues, type ConnectorManifest, type ResourceCapability, type RuntimeConfigDocument, boolean, configSchema, decodeConfig, define, define$1 as defineConfig, number, optional, secret, select, string, toRuntimeDocument };
@@ -1,4 +1,2 @@
1
- import "../constants-BRhIX_rz.js";
2
- import { a as define, c as number, d as select, f as string, i as toRuntimeDocument, l as optional, n as configSchema, o as boolean, r as decodeConfig, s as define$1, u as secret } from "../manifest-ByE6YPG0.js";
3
-
4
- export { boolean, configSchema, decodeConfig, define, define$1 as defineConfig, number, optional, secret, select, string, toRuntimeDocument };
1
+ import { a as define, c as number, d as select, f as string, i as toRuntimeDocument, l as optional, n as configSchema, o as boolean, r as decodeConfig, s as define$1, u as secret } from "../manifest-BGKxmKLy.mjs";
2
+ export { boolean, configSchema, decodeConfig, define, define$1 as defineConfig, number, optional, secret, select, string, toRuntimeDocument };