5 months ago
Description
Currently my Bun scripts after being deployed successfully are being killed with a SIGTERM call.
The bun script simple listen to Supabase realtime (new INSERTS on a table) and then triggers a message to Discord or creates a Linear issue.
Important: the script has to be running 24/7.
Error messages
Image attached
Logs
$ cd packages/linear && bun run start
$ bun run index.ts
Connected to Supabase Realtime
Stopping Container
error: script "start" was terminated by signal SIGTERM (Polite quit request)
error: script "start:linear" was terminated by signal SIGTERM (Polite quit request)
Code
import { serve } from "bun";
import { LinearClient } from "@linear/sdk";
import { createClient } from "@supabase/supabase-js";
import capitalize from "lodash/capitalize";
import { z } from "zod";
// db
import { publicRequestRowSchema } from "@rebalance-dapp/api/db/database-schema";
// helpers
function getSupabaseRealtimeUrl() {
const supabaseUrl = Bun.env.SUPABASE_URL;
return z.string().parse(supabaseUrl);
}
function getSupabaseApiKey() {
const supabaseApiKey = Bun.env.SUPABASE_API_KEY;
return z.string().parse(supabaseApiKey);
}
function getLinearApiKey() {
const linearApiKey = Bun.env.LINEAR_API_KEY;
return z.string().parse(linearApiKey);
}
// constants - secrets
const linearApiKey = getLinearApiKey();
const supabaseApiKey = getSupabaseApiKey();
const supabaseUrl = getSupabaseRealtimeUrl();
// linear
const linearClient = new LinearClient({ apiKey: linearApiKey });
// supabase
const supabase = createClient(supabaseUrl, supabaseApiKey);
const supabaseChannel = supabase.channel("db-channel-linear");
// subscribe to changes
supabaseChannel.on("postgres_changes", { event: "INSERT", schema: "public", table: "request" }, async (payload) => {
try {
const { new: newRecord } = payload;
const parsedNewRecord = publicRequestRowSchema.parse(newRecord);
const message = `.....`;
const response = await linearClient.createIssue({
title,
priority: 0,
id: newRecord.id,
description: message,
teamId: VEDA_LABS_TEAM_ID,
assigneeId: BRYAN_ASSIGNEE_ID,
projectId: SMART_CONTRACTS_PROJECT_ID,
});
if (response.success) {
console.log(`Linear issue created successfully ${parsedNewRecord.id}`);
} else {
console.log(JSON.stringify(response, null, 2));
console.log(`Failed to create Linear issue ${parsedNewRecord.id}`);
}
} catch (error) {
console.log("Error on INSERT");
console.log(JSON.stringify(error, null, 2));
}
});
// check connection status
supabaseChannel.subscribe((status, err) => {
if (status === "SUBSCRIBED") {
console.log("Connected to Supabase Realtime");
}
if (err) {
console.log(JSON.stringify(err, null, 2));
}
if (status === "CHANNEL_ERROR") {
console.log(`There was an error subscribing to channel: ${err instanceof Error ? err.message : err}`);
}
if (status === "TIMED_OUT") {
console.log("Realtime server did not respond in time.");
}
if (status === "CLOSED") {
console.log("Realtime channel was unexpectedly closed.");
}
});
serve({
port: Bun.env.PORT || 3000,
fetch: () => new Response("OK"),
});
That HTTP server (serve call) was an attempt to bypass the SIGTERM call but it failed
Attachments
1 Replies
5 months ago
Hi!
Bun's serve() function does not block the event loop like Node.js http.createServer() does. So even though you "start a server," Bun sees the script as "done" and lets the event loop finish, which may cause the deployment platform to send a SIGTERM to stop the process.
This await new Promise(() => {}) is an infinite promise that keeps the event loop alive forever, effectively making your worker persistent.
Add this to the bottom of your code:// Keep the script running forever
await new Promise(() => {});