Skip to content

Commit

Permalink
feat: add first version
Browse files Browse the repository at this point in the history
  • Loading branch information
darlanalves committed May 8, 2024
1 parent 283b0ee commit 5030916
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: CICD
on:
- push

jobs:
release:
uses: cloud-cli/workflows/.github/workflows/npm-build-release.yml@main
with:
buildCommand: 'npm i'
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,42 @@
# workerd

A daemon to spawn and monitor workers

## Install

```sh
npm i -g @cloud-cli/workerd
```

> Make sure the global NPM folder is part of `$PATH`.
## Usage

Create a file called `workers.yml` in the current folder or in your user home folder:

```yaml
- name: my-worker
run: node my-worker.js
cwd: /home/node-workers
restart: true
restartInterval: 1000
env:
API_KEY: b7ad65b347d6bb7ad65b347d6b
API_URL: https://example.com

- name: other-worker
run: python3 worker.py
cwd: /home/python3-workers
restart: false
```

## Defaults

- `cwd`: the path from where workerd is executed
- `restart`: true
- `restartInterval`: 5 seconds

## Logs

Logs are written per worker, using worker's name.
Specify `SERVICE_LOGS_FOLDER` variable to change the path, default is `/tmp/workerd`.
100 changes: 100 additions & 0 deletions index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env node

import * as Yaml from "js-yaml";
import { exec } from "node:child_process";
import { join } from "node:path";
import {
createWriteStream,
existsSync,
mkdirSync,
readFileSync,
} from "node:fs";

const loadYaml = Yaml.default.load;
const logsFolder = process.env.SERVICE_LOGS_FOLDER || "/tmp/workerd";
const restartInterval = Number(process.env.RESTART_INTERVAL || 5000);
const servicesLog = createLogStream(join(logsFolder, "services.log"));

function startService(service) {
if (!(service.name || service.run)) {
servicesLog.write(`[ERROR] Invalid service: ${JSON.stringify(service)}`);
return;
}

servicesLog.write(`[START] ${service.name || service.run}\n`);
const env = { ...process.env, ...(service.env || {}) };
const ps = exec(service.run, {
cwd: service.cwd || process.cwd(),
env,
});

const logs = createLogStream(
join(logsFolder, service.name + "." + ps.pid + ".log")
);

ps.stdout.pipe(logs);
ps.stderr.pipe(logs);

ps.on("exit", (code) => {
logs.write(`[EXIT] ${code}`);

if (service.restart !== false) {
const interval = service.restartInterval || restartInterval;
setTimeout(() => startService(service), interval);
}
});
}

function createLogStream(file) {
const log = createWriteStream(file, { flags: "a" });
const write = log.write;

log.write = (chunk, ...args) =>
log.writable &&
write.apply(log, [
String(chunk)
.split("\n")
.map((line) =>
line ? `[${new Date().toISOString().slice(0, 19)}] ${line}` : ""
)
.join("\n"),
...args,
]);

return log;
}

function loadServices() {
const candidates = [
join(process.cwd(), "services.yml"),
join(process.env.HOME || "", "services.yml"),
];

for (const file of candidates) {
if (existsSync(file)) {
const list = loadYaml(readFileSync(file, "utf8")).services;

if (!Array.isArray(list)) {
throw new Error(
`Invalid format in ${file}, expected an array. See documentation.`
);
}

return list;
}
}

return [];
}

function start() {
const services = loadServices();

mkdirSync(join(logsFolder), { recursive: true });

for (const s of services) {
startService(s);
}
}

start();
20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@cloud-cli/workerd",
"version": "0.0.0",
"description": "",
"main": "./index.mjs",
"type": "module",
"bin": {
"workerd": "./index.mjs"
},
"scripts": {},
"keywords": [],
"author": {
"name": "Darlan Alves",
"email": "me@darlanalv.es"
},
"license": "MIT",
"dependencies": {
"js-yaml": "^3.13.1"
}
}

0 comments on commit 5030916

Please sign in to comment.