Workers
Background tasks and long-running processes with workers
Overview
Workers in Bunbox run background tasks or long-running processes. Create a worker.ts file in your app/ directory.
Creating a Worker
Create app/worker.ts:
export default async function worker() {
console.log("Worker started");
// Your background task
setInterval(() => {
console.log("Worker running...");
}, 5000);
}Socket Client Worker
Connect to sockets from a worker:
import { SocketClient } from "@ademattos/bunbox/client";
import { ChatProtocol } from "./sockets/chat/protocol";
export default async function worker() {
const socketClient = new SocketClient(
"ws://localhost:3000/sockets/chat",
ChatProtocol,
{ username: "worker-bot" }
);
socketClient.subscribe("chat-message", (message) => {
console.log("Received:", message.data.text);
});
socketClient.publish("chat-message", {
text: "Hello from worker!",
username: "worker-bot",
});
}Cleanup Function
Return a cleanup function for hot reload:
export default async function worker() {
const interval = setInterval(() => {
console.log("Running...");
}, 1000);
// Return cleanup function
return {
close: () => {
clearInterval(interval);
console.log("Worker stopped");
},
};
}Worker Lifecycle
- Workers start when the server starts
- Workers restart on hot reload in development
- Cleanup functions are called before restart
- Workers run in the same process as the server
Use Cases
Background Tasks
export default async function worker() {
// Periodic cleanup
setInterval(async () => {
await cleanupOldData();
}, 3600000); // Every hour
}Socket Clients
export default async function worker() {
const client = new SocketClient("/sockets/notifications", Protocol, {});
client.subscribe("notification", (msg) => {
// Process notifications
});
return {
close: () => client.close(),
};
}Scheduled Jobs
export default async function worker() {
// Run every day at midnight
const scheduleDailyJob = () => {
const now = new Date();
const tomorrow = new Date(now);
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
const msUntilMidnight = tomorrow.getTime() - now.getTime();
setTimeout(() => {
runDailyJob();
scheduleDailyJob(); // Schedule next day
}, msUntilMidnight);
};
scheduleDailyJob();
}Error Handling
Handle errors gracefully:
export default async function worker() {
try {
// Your worker logic
} catch (error) {
console.error("Worker error:", error);
}
}Development vs Production
- In development, workers restart on file changes
- In production, workers run continuously
- Use cleanup functions to prevent resource leaks
Complete Example
import { SocketClient } from "@ademattos/bunbox/client";
import { ChatProtocol } from "./sockets/chat/protocol";
export default async function worker() {
console.log("Chat worker started");
const socketClient = new SocketClient(
"ws://localhost:3000/sockets/chat",
ChatProtocol,
{ username: "bot" }
);
socketClient.subscribe("chat-message", (message) => {
if (message.data.text.includes("hello")) {
socketClient.publish("chat-message", {
text: "Hello! How can I help?",
username: "bot",
});
}
});
return {
close: () => {
socketClient.close();
console.log("Chat worker stopped");
},
};
}