do not allow multiple instances

This commit is contained in:
cupcakearmy 2020-05-17 18:13:50 +02:00
parent f9c645120b
commit 1520e10a59
No known key found for this signature in database
GPG Key ID: D28129AE5654D9D9
4 changed files with 57 additions and 38 deletions

View File

@ -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()
}

View File

@ -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}`)
}

32
src/lock.ts Normal file
View File

@ -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,
})
}

View File

@ -93,8 +93,11 @@ export type Config = {
}
export type Lockfile = {
[name: string]: {
lastRun: number
running: boolean
crons: {
[name: string]: {
lastRun: number
}
}
}