Add event bus and storage layer
This commit is contained in:
parent
9ba51d8e96
commit
488ae82ed6
19 changed files with 537 additions and 21 deletions
|
|
@ -6,7 +6,10 @@
|
|||
"dev": "bun run src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@islandflow/bus": "workspace:*",
|
||||
"@islandflow/config": "workspace:*",
|
||||
"@islandflow/observability": "workspace:*"
|
||||
"@islandflow/observability": "workspace:*",
|
||||
"@islandflow/types": "workspace:*",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,78 @@
|
|||
import { readEnv } from "@islandflow/config";
|
||||
import { createLogger } from "@islandflow/observability";
|
||||
import {
|
||||
SUBJECT_OPTION_PRINTS,
|
||||
STREAM_OPTION_PRINTS,
|
||||
buildDurableConsumer,
|
||||
connectJetStreamWithRetry,
|
||||
ensureStream,
|
||||
subscribeJson
|
||||
} from "@islandflow/bus";
|
||||
import { OptionPrintSchema } from "@islandflow/types";
|
||||
import { z } from "zod";
|
||||
|
||||
const service = "compute";
|
||||
const logger = createLogger({ service });
|
||||
|
||||
logger.info("service starting");
|
||||
const envSchema = z.object({
|
||||
NATS_URL: z.string().default("nats://localhost:4222")
|
||||
});
|
||||
|
||||
const shutdown = (signal: string) => {
|
||||
logger.info("service stopping", { signal });
|
||||
process.exit(0);
|
||||
const env = readEnv(envSchema);
|
||||
|
||||
const run = async () => {
|
||||
logger.info("service starting");
|
||||
|
||||
const { nc, js, jsm } = await connectJetStreamWithRetry(
|
||||
{
|
||||
servers: env.NATS_URL,
|
||||
name: service
|
||||
},
|
||||
{ attempts: 20, delayMs: 500 }
|
||||
);
|
||||
|
||||
await ensureStream(jsm, {
|
||||
name: STREAM_OPTION_PRINTS,
|
||||
subjects: [SUBJECT_OPTION_PRINTS],
|
||||
retention: "limits",
|
||||
storage: "file",
|
||||
discard: "old",
|
||||
max_msgs_per_subject: -1,
|
||||
max_msgs: -1,
|
||||
max_bytes: -1,
|
||||
max_age: 0,
|
||||
num_replicas: 1
|
||||
});
|
||||
|
||||
const opts = buildDurableConsumer("compute-option-prints");
|
||||
|
||||
const subscription = await subscribeJson(js, SUBJECT_OPTION_PRINTS, opts);
|
||||
|
||||
const shutdown = async (signal: string) => {
|
||||
logger.info("service stopping", { signal });
|
||||
await nc.drain();
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on("SIGINT", () => void shutdown("SIGINT"));
|
||||
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
||||
|
||||
for await (const msg of subscription.messages) {
|
||||
try {
|
||||
const print = OptionPrintSchema.parse(subscription.decode(msg));
|
||||
logger.info("received option print", {
|
||||
trace_id: print.trace_id,
|
||||
seq: print.seq,
|
||||
option_contract_id: print.option_contract_id
|
||||
});
|
||||
msg.ack();
|
||||
} catch (error) {
|
||||
logger.error("failed to process option print", {
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
});
|
||||
msg.term();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
process.on("SIGINT", () => shutdown("SIGINT"));
|
||||
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
||||
|
||||
// Keep the process alive until real listeners are wired.
|
||||
setInterval(() => {}, 60_000);
|
||||
await run();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue