create qr-codes by tg bot
Deploy app frontend / app frontend (push) Failing after 48s
Deploy db-migrations / db-migrations (push) Failing after 35s
Deploy service message-delivery-method-web-push / service message-delivery-method-web-push (push) Failing after 53s

This commit is contained in:
2024-12-10 13:21:38 +02:00
parent e9b3df38fe
commit 1810c550ba
91 changed files with 3317 additions and 1909 deletions
@@ -1,64 +0,0 @@
import http from "http";
/**
* Запускает HTTP-сервер для проверки здоровья.
* @param controller - AbortController для управления состоянием здоровья.
* @param defaultPort - Порт для сервера по умолчанию (если не указан в ENV HEALTH_PORT).
* @param defaultHostName - Имя хоста для сервера по умолчанию (если не указан в ENV HEALTH_HOST).
*/
export function startHealthServer(
controller: AbortController,
defaultPort: number = 8000,
defaultHostName: string = "127.0.0.1",
) {
const port = parseInt(process.env.HEALTH_PORT || `${defaultPort}`, 10);
const hostname = process.env.HEALTH_HOST || defaultHostName;
const server = http.createServer((req, res) => {
if (req.url === "/health") {
const signal = controller.signal;
// Если сигнал отмены активирован, сервер помечается как "unhealthy"
if (signal.aborted) {
res.writeHead(500, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
status: "unhealthy",
reason: "Service aborted",
}),
);
return;
}
// Возвращаем стандартный статус "ok", если всё нормально
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
status: "ok",
}),
);
} else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found");
}
});
const { promise, resolve, reject } = Promise.withResolvers<void>();
server.once("error", reject);
server.listen(port, hostname, resolve);
promise.then(() => {
console.log(
`Healthcheck server running on http://${hostname}:${port}/health`,
);
});
// Закрываем сервер при активации AbortController
controller.signal.addEventListener("abort", () => {
console.log("Healthcheck server shutting down due to abort signal.");
reject();
server.close();
});
return promise;
}
@@ -10,11 +10,12 @@ import {
webPushSubscriptionsDb,
userChatSettingsDb,
checkDatabases,
serviceSeqTrackerDb,
} from "./dbs";
import { setupVapidDetails } from "./setupVapidDetails";
import type { MessageDocument } from "@hereconnect/types";
import { ServiceSeqTracker } from "./serviceSeqTracker";
import { startHealthServer } from "./health-server";
import { ServiceSeqTracker } from "@hereconnect/lib-service-seq-tracker";
import { startHealthServer } from "@hereconnect/lib-service-health-checkserver";
const abortController = new AbortController();
@@ -33,6 +34,7 @@ const start = async () => {
const serviceSeqTracker = await ServiceSeqTracker.Init(
"_local/service:message-delivery-method-web-push",
serviceSeqTrackerDb,
);
const changesStream = new CouchDBChangesStream<MessageDocument>(
@@ -56,6 +58,7 @@ const start = async () => {
// Gracefully handle SIGINT
process.on("SIGINT", async () => {
changesStream?.stop();
setTimeout(() => process.exit(1), 5_000).unref();
});
console.info("Service started from sequence", serviceSeqTracker.lastSeq);
@@ -1,43 +0,0 @@
import { serviceSeqTrackerDb, type ServiceSeqTrackerDocument } from "./dbs";
export class ServiceSeqTracker {
/**
* @param _id
* @constructor
*/
static async Init(_id: string) {
const doc = await serviceSeqTrackerDb.get(_id).catch((error) => {
if (error.name === "not_found") {
return {
_id,
lastSeq: "0",
};
}
throw error; // Re-throw other errors
});
return new ServiceSeqTracker(doc);
}
private constructor(private doc: ServiceSeqTrackerDocument) {}
get lastSeq() {
return this.doc.lastSeq;
}
checkNextSeq(seq: number | string) {
if (!this.doc) {
}
const next = parseInt(seq as string, 10);
const current = parseInt(this.doc.lastSeq as string, 10);
if (next < current) {
throw new Error(
`Sequence number is too old: ${seq} (${next} < ${current})`,
);
}
}
saveSeq(seq: number | string) {
this.doc.lastSeq = seq;
return serviceSeqTrackerDb.put(this.doc);
}
}