Ctrl K
ComunidadGuías…

services/retl-runner/src/target-state.ts

Rama newjitsu · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { ScopedTargetState } from "@jitsu/protocols/reverse-etl-runtime";
import type { Database } from "./persistence/database";
import { ensure } from "./persistence/types";

/** Sync scope is supplied by the runner, never by the provider's stored JSON. */
export function createTargetState(
  db: Database,
  scope: { workspaceId: string; id: string },
  stream: string
): ScopedTargetState {
  return {
    read: () =>
      db.transaction(async client => {
        const result = await client.query("SELECT state FROM source_state WHERE sync_id=$1 AND stream=$2", [
          scope.id,
          stream,
        ]);
        return result.rows[0]?.state;
      }),
    create: value =>
      db.transaction(async client => {
        const existing = await client.query("SELECT 1 FROM reverse_sync_control WHERE workspace_id=$1 AND sync_id=$2", [
          scope.workspaceId,
          scope.id,
        ]);
        ensure(!existing.rowCount, "Managed audience state is missing; preserve delivery state and reconcile");
        await client.query(
          "INSERT INTO source_state(sync_id,stream,state,timestamp) VALUES($1,$2,$3,clock_timestamp()) ON CONFLICT(sync_id,stream) DO NOTHING",
          [scope.id, stream, JSON.stringify(value)]
        );
      }),
    compareAndSet: (expected, value) =>
      db.transaction(async client => {
        const result = await client.query(
          "UPDATE source_state SET state=$3,timestamp=clock_timestamp() WHERE sync_id=$1 AND stream=$2 AND state=$4::jsonb",
          [scope.id, stream, JSON.stringify(value), JSON.stringify(expected)]
        );
        return result.rowCount === 1;
      }),
  };
}