From 1520e10a59cb194d22427510edd528d03690baac Mon Sep 17 00:00:00 2001 From: cupcakearmy Date: Sun, 17 May 2020 18:13:50 +0200 Subject: [PATCH] do not allow multiple instances --- src/autorestic.ts | 16 ++++++++++++++-- src/cron.ts | 40 ++++++---------------------------------- src/lock.ts | 32 ++++++++++++++++++++++++++++++++ src/types.ts | 7 +++++-- 4 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 src/lock.ts diff --git a/src/autorestic.ts b/src/autorestic.ts index 0289701..d584431 100644 --- a/src/autorestic.ts +++ b/src/autorestic.ts @@ -4,11 +4,11 @@ import minimist from 'minimist' import { init } from './config' import handlers, { error, help } from './handlers' import { Config } from './types' - - +import { readLock, writeLock, unlock } from './lock' process.on('uncaughtException', err => { console.log(err.message) + unlock() process.exit(1) }) @@ -36,6 +36,17 @@ export let config: Config async function main() { config = init() + // Don't let 2 instances run on the same config + const lock = readLock() + if (lock.running) { + console.log('An instance of autorestic is already running for this config file'.red) + return + } + writeLock({ + ...lock, + running: true, + }) + // For dev // return await handlers['cron']([], { ...flags, all: true }) @@ -46,6 +57,7 @@ async function main() { const fn = handlers[command] || error await fn(args, flags) + unlock() } diff --git a/src/cron.ts b/src/cron.ts index b70704f..087d23a 100644 --- a/src/cron.ts +++ b/src/cron.ts @@ -1,49 +1,21 @@ -import fs from 'fs' - import CronParser from 'cron-parser' import { config } from './autorestic' import { checkAndConfigureBackendsForLocations } from './backend' -import { Location, Lockfile } from './types' +import { Location } from './types' import { backupLocation } from './backup' -import { pathRelativeToConfigFile } from './utils' +import { readLock, writeLock } from './lock' -const getLockFileName = () => { - const LOCK_FILE = '.autorestic.lock' - return pathRelativeToConfigFile(LOCK_FILE) -} - -const readLock = (): Lockfile => { - const name = getLockFileName() - let lock = {} - try { - lock = JSON.parse(fs.readFileSync(name, { encoding: 'utf-8' })) - } catch { } - return lock -} -const writeLock = (diff: Lockfile = {}) => { - const name = getLockFileName() - const newLock = Object.assign( - readLock(), - diff - ) - fs.writeFileSync(name, JSON.stringify(newLock, null, 2), { encoding: 'utf-8' }) -} - const runCronForLocation = (name: string, location: Location) => { - const lock = readLock()[name] + const lock = readLock() const parsed = CronParser.parseExpression(location.cron || '') const last = parsed.prev() - if (!lock || last.toDate().getTime() > lock.lastRun) { + if (!lock.crons[name] || last.toDate().getTime() > lock.crons[name].lastRun) { backupLocation(name, location) - writeLock({ - [name]: { - ...lock, - lastRun: Date.now() - } - }) + lock.crons[name] = { lastRun: Date.now() } + writeLock(lock) } else { console.log(`${name.yellow} ▶ Skipping. Sheduled for: ${parsed.next().toString().underline.blue}`) } diff --git a/src/lock.ts b/src/lock.ts new file mode 100644 index 0000000..962d463 --- /dev/null +++ b/src/lock.ts @@ -0,0 +1,32 @@ +import fs from 'fs' + +import { pathRelativeToConfigFile } from "./utils" +import { Lockfile } from "./types" + +export const getLockFileName = () => { + const LOCK_FILE = '.autorestic.lock' + return pathRelativeToConfigFile(LOCK_FILE) +} + +export const readLock = (): Lockfile => { + const name = getLockFileName() + let lock = { + running: false, + crons: {} + } + try { + lock = JSON.parse(fs.readFileSync(name, { encoding: 'utf-8' })) + } catch { } + return lock +} +export const writeLock = (lock: Lockfile) => { + const name = getLockFileName() + fs.writeFileSync(name, JSON.stringify(lock, null, 2), { encoding: 'utf-8' }) +} + +export const unlock = () => { + writeLock({ + ...readLock(), + running: false, + }) +} \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index 5cad816..1380d22 100644 --- a/src/types.ts +++ b/src/types.ts @@ -93,8 +93,11 @@ export type Config = { } export type Lockfile = { - [name: string]: { - lastRun: number + running: boolean + crons: { + [name: string]: { + lastRun: number + } } }