feat: add metadata server and build config

main
Arseniusz 2 years ago
parent 3f814cc97f
commit 694ddd0b87

@ -0,0 +1,9 @@
FROM node:20-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --omit=dev
COPY src/. .
EXPOSE 4000 7000
CMD [ "node", "src/main.js" ]

@ -0,0 +1,21 @@
STORAGE_URL = gitea.bjornmossa.net
IMAGE_NAME = $(STORAGE_URL)/radioiceberg/metadata
GIT_TAG = $(shell git describe --abbrev=0 --tags)
login:
docker login $(STORAGE_URL)
start:
npx live-server ./src
build:
docker build . -t $(IMAGE_NAME):$(GIT_TAG)
bump-latest:
docker tag $(IMAGE_NAME):$(GIT_TAG) $(IMAGE_NAME):latest
push-current: login
docker push $(IMAGE_NAME):$(GIT_TAG)
push-latest: login
docker push $(IMAGE_NAME):latest

@ -0,0 +1,23 @@
{
"name": "iceberg-metadata",
"version": "1.0.0",
"description": "Microservice for updating metadata on radio",
"main": "main.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Arseniusz/radioiceberg.git"
},
"author": "radio iceberg team",
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/Arseniusz/radioiceberg/issues"
},
"homepage": "https://github.com/Arseniusz/radioiceberg#readme",
"dependencies": {
"ws": "^8.13.0"
}
}

@ -0,0 +1,49 @@
import { createServer } from "node:http";
import { randomUUID } from "node:crypto";
import { WebSocketServer } from "ws";
import { notifier } from "./notifier.js";
const wss = new WebSocketServer({ port: 7000 });
wss.on("connection", (ws) => {
const id = randomUUID();
const message = {
command: "clientConnected",
data: {
socket: ws,
id,
},
};
notifier.processMessage(message);
ws.on("close", () => {
const message = {
command: "cliendDisconnected",
data: {
id,
},
};
notifier.processMessage(message);
});
});
createServer((req, res) => {
let body = "";
req.on("data", (chunk) => {
body += chunk;
});
req.on("end", () => {
try {
const message = JSON.parse(body);
notifier.processMessage(message);
} catch (error) {
console.error(error);
}
});
res.end();
}).listen(4000);

@ -0,0 +1,60 @@
import { state } from "./state.js";
function updateMeta(message) {
const { data } = message;
this.state.lastPlayed = data;
this.notifyAll(message);
}
function startOnline(message) {
this.state.isOnline = true;
this.notifyAll(message);
}
function stopOnline(message) {
this.state.isOnline = false;
this.notifyAll(message);
}
function addClient({ data }) {
const { socket, id } = data;
this.clients.set(id, socket);
this.notifyOne(socket, { command: "setState", data: this.state });
}
function deleteClient({ data }) {
const { id } = data;
this.clients.delete(id);
}
const actions = {
clientConnected: addClient,
cliendDisconnected: deleteClient,
metadataChange: updateMeta,
liveStarted: startOnline,
liveEnded: stopOnline,
};
const notifier = {
__proto__: state,
notifyAll: function (message) {
const messageStrinified = JSON.stringify(message);
this.clients.forEach((c) => c.send(messageStrinified));
},
notifyOne: function (socket, message) {
const messageStrinified = JSON.stringify(message);
console.log("NOTIFY ONE:", message);
socket.send(messageStrinified);
},
processMessage: function (message) {
const action = actions[message.command];
if (action) {
action.call(this, message);
console.log("PERFORM ACTION", message.command);
} else {
console.log("no avaible command for state mutation", message.command);
}
},
};
export { notifier };

@ -0,0 +1,9 @@
const state = {
state: {
lastPlayed: null,
isOnline: false,
},
clients: new Map(),
};
export { state };