* Persist a sanitized batch: one `events` row per event, plus the machine×day and * first-seen bookkeeping the dashboard's retention/activation panels need. One D1 * `batch()` = one implicit transaction = one round trip. * * Fail-silent by design: the client treats every response as final and ne
( env: Env, machineId: string, common: JsonObject, batch: StoredEvent[], )
| 214 | * logged (Workers Logs) with counts only — never the payload. |
| 215 | */ |
| 216 | async function writeToD1( |
| 217 | env: Env, |
| 218 | machineId: string, |
| 219 | common: JsonObject, |
| 220 | batch: StoredEvent[], |
| 221 | ): Promise<void> { |
| 222 | try { |
| 223 | const receivedAt = new Date().toISOString(); |
| 224 | const insertEvent = env.DB.prepare(INSERT_EVENT); |
| 225 | const stmts: D1PreparedStatement[] = []; |
| 226 | // Envelope columns are identical for every row in the batch. |
| 227 | const envelopeCols = [ |
| 228 | asText(common.codegraph_version), |
| 229 | asText(common.os), |
| 230 | asText(common.arch), |
| 231 | asInt(common.node_major), |
| 232 | asFlag(common.ci), |
| 233 | asInt(common.schema_version), |
| 234 | ] as const; |
| 235 | // A batch can span days (offline buffers hold completed-day rollups), so |
| 236 | // machine_days gets one row per distinct day rather than one per batch. |
| 237 | const days = new Set<string>(); |
| 238 | |
| 239 | for (const e of batch) { |
| 240 | const day = (e.ts ?? receivedAt).slice(0, 10); |
| 241 | days.add(day); |
| 242 | stmts.push( |
| 243 | insertEvent.bind( |
| 244 | receivedAt, |
| 245 | e.ts ?? null, |
| 246 | day, |
| 247 | e.event, |
| 248 | machineId, |
| 249 | ...envelopeCols, |
| 250 | JSON.stringify(e.props), |
| 251 | ), |
| 252 | ); |
| 253 | } |
| 254 | |
| 255 | const prod = common.ci === true ? 0 : 1; |
| 256 | const upsertDay = env.DB.prepare(UPSERT_MACHINE_DAY); |
| 257 | for (const day of days) stmts.push(upsertDay.bind(machineId, day, prod)); |
| 258 | |
| 259 | const firstDay = [...days].sort()[0]; |
| 260 | if (firstDay !== undefined) { |
| 261 | stmts.push(env.DB.prepare(UPSERT_FIRST_SEEN).bind(machineId, firstDay)); |
| 262 | } |
| 263 | |
| 264 | await env.DB.batch(stmts); |
| 265 | } catch (err) { |
| 266 | console.error(JSON.stringify({ msg: 'd1 write failed', err: String(err), events: batch.length })); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | export default { |
| 271 | async fetch(request, env, ctx): Promise<Response> { |