Skip to content

Instantly share code, notes, and snippets.

@maiah
Last active July 2, 2026 04:19
Show Gist options
  • Select an option

  • Save maiah/46e65fa88d6f10fa0245e6e64942038f to your computer and use it in GitHub Desktop.

Select an option

Save maiah/46e65fa88d6f10fa0245e6e64942038f to your computer and use it in GitHub Desktop.
Spawn
import { Semaphore } from "es-toolkit";
const totalCpuCores = 8; // TODO: Should be set to total number of cpu cores
const totalClients = Math.ceil(totalCpuCores * 1.5); // We want to have more clients than the number of cpu cores to avoid starvation
const lock = new Semaphore(totalClients);
class RpcClient {
createAccount(name: string): Promise<string> {
return Promise.resolve(`Account ${name} created`);
}
onError(callback: (code: number | Error) => void) {
callback(new Error("Error"));
}
onExit(callback: (code: number) => void) {
callback(0);
}
}
const rpcClients: RpcClient[] = [];
function createClient(id: number) {
const rpcClient = new RpcClient();
rpcClient.onError(() => {
// TODO: Implement exponential backoff on retrying to create a new client
setTimeout(() => {
const newRpcClient = createClient(id);
rpcClients.splice(id, 1, newRpcClient);
}, 1_000);
});
rpcClient.onExit((code: number) => {
if (code !== 0) {
// TODO: Implement exponential backoff on retrying to create a new client
setTimeout(() => {
const newRpcClient = createClient(id);
rpcClients.splice(id, 1, newRpcClient);
}, 1_000);
}
});
return rpcClient;
}
for (let i = 0; i < totalClients; i++) {
rpcClients.push(createClient(i));
}
let currentClient = 0;
function getNextRpcClient() {
if (currentClient >= rpcClients.length) {
currentClient = 0;
}
// TODO: Implement a check if client is in error state and if so, retry to create a new client
const client = rpcClients[currentClient];
currentClient++;
return client;
}
async function spawn<T>(fn: (client: RpcClient) => Promise<T>) {
await lock.acquire();
try {
const client = getNextRpcClient();
return await fn(client);
} catch (error) {
console.error("Error in spawn:", error);
} finally {
lock.release();
}
}
async function getRpcClient() {
await lock.acquire();
return {
client: getNextRpcClient(),
release: () => lock.release(),
};
}
async function main() {
const account = await spawn(async (client) => {
return await client.createAccount("John Doe");
});
console.log("account:", account);
const { client, release } = await getRpcClient();
try {
await client.createAccount("John Doe");
} finally {
release();
}
}
main().catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment