import {
  WORKFLOW_GUARD_KV_KEY,
  workflow
} from "./chunk-74ER4FEE.js";
import {
  actor,
  queue
} from "./chunk-OONQLPOH.js";
import {
  db
} from "./chunk-KJSYAUOM.js";
import {
  getLogger,
  promiseWithResolvers
} from "./chunk-IZ4M5TJU.js";

// src/driver-test-suite/log.ts
function logger() {
  return getLogger("test-suite");
}

// fixtures/driver-test-suite/hibernation.ts
var HIBERNATION_SLEEP_TIMEOUT = 500;
var hibernationActor = actor({
  state: {
    sleepCount: 0,
    wakeCount: 0
  },
  createConnState: (c) => {
    return {
      count: 0,
      connectCount: 0,
      disconnectCount: 0
    };
  },
  onWake: (c) => {
    c.state.wakeCount += 1;
  },
  onSleep: (c) => {
    c.state.sleepCount += 1;
  },
  onConnect: (c, conn) => {
    conn.state.connectCount += 1;
  },
  onDisconnect: (c, conn) => {
    conn.state.disconnectCount += 1;
  },
  actions: {
    // Basic RPC that returns a simple value
    ping: (c) => {
      return "pong";
    },
    // Increment the connection's count
    connIncrement: (c) => {
      c.conn.state.count += 1;
      return c.conn.state.count;
    },
    // Get the connection's count
    getConnCount: (c) => {
      return c.conn.state.count;
    },
    // Get the connection's lifecycle counts
    getConnLifecycleCounts: (c) => {
      return {
        connectCount: c.conn.state.connectCount,
        disconnectCount: c.conn.state.disconnectCount
      };
    },
    // Get all connection IDs
    getConnectionIds: (c) => {
      return c.conns.entries().map((x) => x[0]).toArray();
    },
    // Get actor sleep/wake counts
    getActorCounts: (c) => {
      return {
        sleepCount: c.state.sleepCount,
        wakeCount: c.state.wakeCount
      };
    },
    // Trigger sleep
    triggerSleep: (c) => {
      c.sleep();
    }
  },
  options: {
    sleepTimeout: HIBERNATION_SLEEP_TIMEOUT
  }
});

// fixtures/driver-test-suite/sleep.ts
var SLEEP_TIMEOUT = 1e3;
var sleep = actor({
  state: { startCount: 0, sleepCount: 0 },
  onWake: (c) => {
    c.state.startCount += 1;
  },
  onSleep: (c) => {
    c.state.sleepCount += 1;
  },
  actions: {
    triggerSleep: (c) => {
      c.sleep();
    },
    getCounts: (c) => {
      return {
        startCount: c.state.startCount,
        sleepCount: c.state.sleepCount
      };
    },
    setAlarm: async (c, duration) => {
      await c.schedule.after(duration, "onAlarm");
    },
    onAlarm: (c) => {
      c.log.info("alarm called");
    }
  },
  options: {
    sleepTimeout: SLEEP_TIMEOUT
  }
});
var sleepWithLongRpc = actor({
  state: { startCount: 0, sleepCount: 0 },
  createVars: () => ({}),
  onWake: (c) => {
    c.state.startCount += 1;
  },
  onSleep: (c) => {
    c.state.sleepCount += 1;
  },
  actions: {
    getCounts: (c) => {
      return {
        startCount: c.state.startCount,
        sleepCount: c.state.sleepCount
      };
    },
    longRunningRpc: async (c) => {
      c.log.info("starting long running rpc");
      c.vars.longRunningResolve = promiseWithResolvers((reason) => c.log.warn({ msg: "unhandled long running rpc rejection", reason }));
      c.broadcast("waiting");
      await c.vars.longRunningResolve.promise;
      c.log.info("finished long running rpc");
    },
    finishLongRunningRpc: (c) => {
      var _a;
      return (_a = c.vars.longRunningResolve) == null ? void 0 : _a.resolve();
    }
  },
  options: {
    sleepTimeout: SLEEP_TIMEOUT
  }
});
var sleepWithRawHttp = actor({
  state: { startCount: 0, sleepCount: 0, requestCount: 0 },
  onWake: (c) => {
    c.state.startCount += 1;
  },
  onSleep: (c) => {
    c.state.sleepCount += 1;
  },
  onRequest: async (c, request) => {
    c.state.requestCount += 1;
    const url = new URL(request.url);
    if (url.pathname === "/long-request") {
      const duration = parseInt(
        url.searchParams.get("duration") || "1000"
      );
      c.log.info({ msg: "starting long fetch request", duration });
      await new Promise((resolve) => setTimeout(resolve, duration));
      c.log.info("finished long fetch request");
      return new Response(JSON.stringify({ completed: true }), {
        headers: { "Content-Type": "application/json" }
      });
    }
    return new Response("Not Found", { status: 404 });
  },
  actions: {
    getCounts: (c) => {
      return {
        startCount: c.state.startCount,
        sleepCount: c.state.sleepCount,
        requestCount: c.state.requestCount
      };
    }
  },
  options: {
    sleepTimeout: SLEEP_TIMEOUT
  }
});
var sleepWithRawWebSocket = actor({
  state: { startCount: 0, sleepCount: 0, connectionCount: 0 },
  onWake: (c) => {
    c.state.startCount += 1;
  },
  onSleep: (c) => {
    c.state.sleepCount += 1;
  },
  onWebSocket: (c, websocket) => {
    c.state.connectionCount += 1;
    c.log.info({
      msg: "websocket connected",
      connectionCount: c.state.connectionCount
    });
    websocket.send(
      JSON.stringify({
        type: "connected",
        connectionCount: c.state.connectionCount
      })
    );
    websocket.addEventListener("message", (event) => {
      const data = event.data;
      if (typeof data === "string") {
        try {
          const parsed = JSON.parse(data);
          if (parsed.type === "getCounts") {
            websocket.send(
              JSON.stringify({
                type: "counts",
                startCount: c.state.startCount,
                sleepCount: c.state.sleepCount,
                connectionCount: c.state.connectionCount
              })
            );
          } else if (parsed.type === "keepAlive") {
            websocket.send(JSON.stringify({ type: "ack" }));
          }
        } catch {
          websocket.send(data);
        }
      }
    });
    websocket.addEventListener("close", () => {
      c.state.connectionCount -= 1;
      c.log.info({
        msg: "websocket disconnected",
        connectionCount: c.state.connectionCount
      });
    });
  },
  actions: {
    getCounts: (c) => {
      return {
        startCount: c.state.startCount,
        sleepCount: c.state.sleepCount,
        connectionCount: c.state.connectionCount
      };
    }
  },
  options: {
    sleepTimeout: SLEEP_TIMEOUT
  }
});
var sleepWithNoSleepOption = actor({
  state: { startCount: 0, sleepCount: 0 },
  onWake: (c) => {
    c.state.startCount += 1;
  },
  onSleep: (c) => {
    c.state.sleepCount += 1;
  },
  actions: {
    getCounts: (c) => {
      return {
        startCount: c.state.startCount,
        sleepCount: c.state.sleepCount
      };
    }
  },
  options: {
    sleepTimeout: SLEEP_TIMEOUT,
    noSleep: true
  }
});

// fixtures/driver-test-suite/run.ts
var RUN_SLEEP_TIMEOUT = 1e3;
var runWithTicks = actor({
  state: {
    tickCount: 0,
    lastTickAt: 0,
    runStarted: false,
    runExited: false
  },
  run: async (c) => {
    c.state.runStarted = true;
    c.log.info("run handler started");
    while (!c.aborted) {
      c.state.tickCount += 1;
      c.state.lastTickAt = Date.now();
      c.log.info({ msg: "tick", tickCount: c.state.tickCount });
      await new Promise((resolve) => {
        const timeout = setTimeout(resolve, 50);
        c.abortSignal.addEventListener(
          "abort",
          () => {
            clearTimeout(timeout);
            resolve();
          },
          { once: true }
        );
      });
    }
    c.state.runExited = true;
    c.log.info("run handler exiting gracefully");
  },
  actions: {
    getState: (c) => ({
      tickCount: c.state.tickCount,
      lastTickAt: c.state.lastTickAt,
      runStarted: c.state.runStarted,
      runExited: c.state.runExited
    })
  },
  options: {
    sleepTimeout: RUN_SLEEP_TIMEOUT,
    runStopTimeout: 1e3
  }
});
var runWithQueueConsumer = actor({
  state: {
    messagesReceived: [],
    runStarted: false,
    wakeCount: 0
  },
  onWake: (c) => {
    c.state.wakeCount += 1;
  },
  run: async (c) => {
    c.state.runStarted = true;
    c.log.info("run handler started, waiting for messages");
    while (!c.aborted) {
      const messages = await c.queue.next({ names: ["messages"] });
      const message = messages[0];
      if (message) {
        c.log.info({ msg: "received message", body: message.body });
        c.state.messagesReceived.push({
          name: message.name,
          body: message.body
        });
      }
    }
    c.log.info("run handler exiting gracefully");
  },
  actions: {
    getState: (c) => ({
      messagesReceived: c.state.messagesReceived,
      runStarted: c.state.runStarted,
      wakeCount: c.state.wakeCount
    }),
    sendMessage: async (c, body) => {
      const client = c.client();
      const handle = client.runWithQueueConsumer.getForId(c.actorId);
      await handle.send("messages", body);
      return true;
    }
  },
  options: {
    sleepTimeout: RUN_SLEEP_TIMEOUT,
    runStopTimeout: 1e3
  }
});
var runWithEarlyExit = actor({
  state: {
    runStarted: false,
    destroyCalled: false
  },
  run: async (c) => {
    c.state.runStarted = true;
    c.log.info("run handler started, will exit after delay");
    await new Promise((resolve) => setTimeout(resolve, 200));
    c.log.info("run handler exiting early");
  },
  onDestroy: (c) => {
    c.state.destroyCalled = true;
  },
  actions: {
    getState: (c) => ({
      runStarted: c.state.runStarted,
      destroyCalled: c.state.destroyCalled
    })
  },
  options: {
    sleepTimeout: RUN_SLEEP_TIMEOUT
  }
});
var runWithError = actor({
  state: {
    runStarted: false,
    destroyCalled: false
  },
  run: async (c) => {
    c.state.runStarted = true;
    c.log.info("run handler started, will throw error");
    await new Promise((resolve) => setTimeout(resolve, 200));
    throw new Error("intentional error in run handler");
  },
  onDestroy: (c) => {
    c.state.destroyCalled = true;
  },
  actions: {
    getState: (c) => ({
      runStarted: c.state.runStarted,
      destroyCalled: c.state.destroyCalled
    })
  },
  options: {
    sleepTimeout: RUN_SLEEP_TIMEOUT
  }
});
var runWithoutHandler = actor({
  state: {
    wakeCount: 0
  },
  onWake: (c) => {
    c.state.wakeCount += 1;
  },
  actions: {
    getState: (c) => ({
      wakeCount: c.state.wakeCount
    })
  },
  options: {
    sleepTimeout: RUN_SLEEP_TIMEOUT
  }
});

// fixtures/driver-test-suite/workflow.ts
import { Loop } from "@rivetkit/workflow-engine";
var WORKFLOW_QUEUE_NAME = "workflow-default";
var workflowCounterActor = actor({
  state: {
    runCount: 0,
    guardTriggered: false,
    history: []
  },
  run: workflow(async (ctx) => {
    await ctx.loop("counter", async (loopCtx) => {
      try {
        loopCtx.state;
      } catch {
      }
      await loopCtx.step("increment", async () => {
        incrementWorkflowCounter(loopCtx);
      });
      await loopCtx.sleep("idle", 25);
      return Loop.continue(void 0);
    });
  }),
  actions: {
    getState: async (c) => {
      const guardFlag = await c.kv.get(WORKFLOW_GUARD_KV_KEY);
      if (guardFlag === "true") {
        c.state.guardTriggered = true;
      }
      return c.state;
    }
  },
  options: {
    sleepTimeout: 50
  }
});
var workflowQueueActor = actor({
  state: {
    received: []
  },
  queues: {
    [WORKFLOW_QUEUE_NAME]: queue()
  },
  run: workflow(async (ctx) => {
    await ctx.loop("queue", async (loopCtx) => {
      const message = await loopCtx.queue.next("queue-wait", {
        names: [WORKFLOW_QUEUE_NAME],
        completable: true
      });
      if (!message.complete) {
        return Loop.continue(void 0);
      }
      const complete = message.complete;
      await loopCtx.step("store-message", async () => {
        await storeWorkflowQueueMessage(loopCtx, message.body, complete);
      });
      return Loop.continue(void 0);
    });
  }),
  actions: {
    getMessages: (c) => c.state.received,
    sendAndWait: async (c, payload) => {
      const client = c.client();
      const handle = client.workflowQueueActor.getForId(c.actorId);
      return await handle.send(
        WORKFLOW_QUEUE_NAME,
        payload,
        { wait: true, timeout: 1e3 }
      );
    }
  }
});
var workflowAccessActor = actor({
  db: db({
    onMigrate: async (rawDb) => {
      await rawDb.execute(`
				CREATE TABLE IF NOT EXISTS workflow_access_log (
					id INTEGER PRIMARY KEY AUTOINCREMENT,
					created_at INTEGER NOT NULL
				)
			`);
    }
  }),
  state: {
    outsideDbError: null,
    outsideClientError: null,
    insideDbCount: 0,
    insideClientAvailable: false
  },
  run: workflow(async (ctx) => {
    await ctx.loop("access", async (loopCtx) => {
      let outsideDbError = null;
      let outsideClientError = null;
      try {
        loopCtx.db;
      } catch (error) {
        outsideDbError = error instanceof Error ? error.message : String(error);
      }
      try {
        loopCtx.client();
      } catch (error) {
        outsideClientError = error instanceof Error ? error.message : String(error);
      }
      await loopCtx.step("access-step", async () => {
        await updateWorkflowAccessState(
          loopCtx,
          outsideDbError,
          outsideClientError
        );
      });
      await loopCtx.sleep("idle", 25);
      return Loop.continue(void 0);
    });
  }),
  actions: {
    getState: (c) => c.state
  }
});
var workflowSleepActor = actor({
  state: {
    ticks: 0
  },
  run: workflow(async (ctx) => {
    await ctx.loop("sleep", async (loopCtx) => {
      await loopCtx.step("tick", async () => {
        incrementWorkflowSleepTick(loopCtx);
      });
      await loopCtx.sleep("delay", 40);
      return Loop.continue(void 0);
    });
  }),
  actions: {
    getState: (c) => c.state
  },
  options: {
    sleepTimeout: 50
  }
});
var workflowStopTeardownActor = actor({
  state: {
    wakeAts: [],
    sleepAts: []
  },
  queues: {
    never: queue()
  },
  onWake: (c) => {
    c.state.wakeAts.push(Date.now());
  },
  onSleep: (c) => {
    c.state.sleepAts.push(Date.now());
  },
  run: workflow(async (ctx) => {
    await ctx.loop("wait-forever", async (loopCtx) => {
      await loopCtx.queue.next("wait-for-never", {
        names: ["never"]
      });
      return Loop.continue(void 0);
    });
  }),
  actions: {
    getTimeline: (c) => ({
      wakeAts: [...c.state.wakeAts],
      sleepAts: [...c.state.sleepAts]
    })
  },
  options: {
    sleepTimeout: 75,
    runStopTimeout: 2e3
  }
});
function incrementWorkflowCounter(ctx) {
  ctx.state.runCount += 1;
  ctx.state.history.push(ctx.state.runCount);
}
async function storeWorkflowQueueMessage(ctx, body, complete) {
  ctx.state.received.push(body);
  await complete({ echo: body });
}
async function updateWorkflowAccessState(ctx, outsideDbError, outsideClientError) {
  var _a;
  await ctx.db.execute(
    `INSERT INTO workflow_access_log (created_at) VALUES (${Date.now()})`
  );
  const counts = await ctx.db.execute(
    `SELECT COUNT(*) as count FROM workflow_access_log`
  );
  const client = ctx.client();
  ctx.state.outsideDbError = outsideDbError;
  ctx.state.outsideClientError = outsideClientError;
  ctx.state.insideDbCount = ((_a = counts[0]) == null ? void 0 : _a.count) ?? 0;
  ctx.state.insideClientAvailable = typeof client.workflowQueueActor.getForId === "function";
}
function incrementWorkflowSleepTick(ctx) {
  ctx.state.ticks += 1;
}

export {
  logger,
  HIBERNATION_SLEEP_TIMEOUT,
  hibernationActor,
  SLEEP_TIMEOUT,
  sleep,
  sleepWithLongRpc,
  sleepWithRawHttp,
  sleepWithRawWebSocket,
  sleepWithNoSleepOption,
  RUN_SLEEP_TIMEOUT,
  runWithTicks,
  runWithQueueConsumer,
  runWithEarlyExit,
  runWithError,
  runWithoutHandler,
  WORKFLOW_QUEUE_NAME,
  workflowCounterActor,
  workflowQueueActor,
  workflowAccessActor,
  workflowSleepActor,
  workflowStopTeardownActor
};
//# sourceMappingURL=chunk-NAM3D5W5.js.map