diff --git a/src/check-in.ts b/src/check-in.ts new file mode 100644 index 0000000..c4965a4 --- /dev/null +++ b/src/check-in.ts @@ -0,0 +1,26 @@ +import { kvDataStorage } from './kv-data-storage'; +import { notificationService } from './notification'; + +export async function dailyCheckIn() { + const lastCheckIn = kvDataStorage.get('lastCheckIn'); + if (lastCheckIn && Date.now() - lastCheckIn < 1000 * 60 * 60 * 23) { + return; + } + + //get stats + const lastCheckInMessage = new Date(lastCheckIn || Date.now()).toLocaleString('lt-LT'); + const numPortsChanged = kvDataStorage.get('numPortsChanged') || 0; + const numRuns = kvDataStorage.get('numRuns') || 0; + const isServiceRunning = kvDataStorage.get('isServiceRunning') || false; + const lastRun = kvDataStorage.get('lastRun'); + let lastRunMessage = 'never'; + if (lastRun) { + lastRunMessage = new Date(lastRun).toLocaleString('lt-LT'); + } + + //reset data + await kvDataStorage.set({ lastCheckIn: Date.now() , numPortsChanged: 0, numRuns: 0 }); + + const message = `Daily check-in. Last check-in: ${lastCheckInMessage}. Number of ports changed: ${numPortsChanged}. Number of checks: ${numRuns}. Service running: ${isServiceRunning}. Last run: ${lastRunMessage}`; + await notificationService.sendNotification(message); +} diff --git a/src/kv-data-storage.ts b/src/kv-data-storage.ts new file mode 100644 index 0000000..b1dca4a --- /dev/null +++ b/src/kv-data-storage.ts @@ -0,0 +1,39 @@ +import { writeFile } from 'fs/promises'; +import { join } from 'path'; +import { existsSync, readFileSync } from 'fs'; + +class KeyValueDataStorage { + private readonly data: Record = {}; + private readonly filePath: string; + + constructor() { + this.filePath = join(__dirname, 'kv-data.json'); + this.data = {}; + if (existsSync(this.filePath)) { + try { + const rawData = readFileSync(this.filePath); + this.data = JSON.parse(rawData.toString()); + } catch (e) { + this.data = {}; + } + } + } + + get(key: string): T | null { + if (this.data[key]) { + return this.data[key] as T; + } + + return null; + } + + async set(data: Record): Promise { + Object.keys(data).forEach((key) => { + this.data[key] = data[key]; + }); + + await writeFile(this.filePath, JSON.stringify(this.data, null, 2)); + } +} + +export const kvDataStorage = new KeyValueDataStorage(); diff --git a/src/set-port-flow.ts b/src/set-port-flow.ts index 6967e07..9760b82 100644 --- a/src/set-port-flow.ts +++ b/src/set-port-flow.ts @@ -2,28 +2,44 @@ import { Transmission } from './transmission'; import { DockerContainer } from './docker'; import { settings } from './settings'; import { notificationService } from './notification'; +import { kvDataStorage } from './kv-data-storage'; +import { dailyCheckIn } from './check-in'; async function downTransmission(transmissionContainer: DockerContainer, reason: string) { console.log(reason); + await kvDataStorage.set({ isServiceRunning: false }); await notificationService.sendNotification(reason, true); return await transmissionContainer.down(); } export async function setPortFlow() { - console.log('Starting set port flow'); const transmissionClient = new Transmission(settings.transmission); const transmissionContainer = new DockerContainer( settings.dockerTransmission.service, settings.dockerTransmission.cwd, settings.dockerTransmission.serviceName ); + try { + await doSetPortFlow(transmissionClient, transmissionContainer); + } catch (e) { + console.error('Error in set port flow', e); + await downTransmission(transmissionContainer, `Shutting down: error in set port flow.`); + } + await dailyCheckIn(); +} + +async function doSetPortFlow(transmissionClient: Transmission, transmissionContainer: DockerContainer) { + console.log('Starting set port flow'); const containerState = await transmissionContainer.getState(); if (containerState?.state !== 'running') { console.log('Transmission service is not running'); + await kvDataStorage.set({ isServiceRunning: false }); return; } + const numRuns = kvDataStorage.get('numRuns') || 0; + await kvDataStorage.set({ isServiceRunning: true, numRuns: numRuns + 1, lastRun: Date.now() }); console.log(`Gathering info`); const port = await transmissionClient.getPort(); @@ -88,6 +104,9 @@ export async function setPortFlow() { console.log(`Setting port to ${newPort}`); await transmissionClient.setPort(newPort); + const numPortsChanged = kvDataStorage.get('numPortsChanged') || 0; + await kvDataStorage.set({ numPortsChanged: numPortsChanged + 1 }); + console.log('Port set'); const newPortOpen = await transmissionClient.testPortIfOpen(); console.log(`Port ${newPort} is open: ${newPortOpen}`);