161 lines
4.5 KiB
Swift
161 lines
4.5 KiB
Swift
//
|
|
// KissBatch.swift
|
|
// KissMeBatch
|
|
//
|
|
// Created by ened-book-m1 on 2023/06/12.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
|
|
struct Batch: Codable {
|
|
let groups: [Group]
|
|
|
|
struct Group: Codable {
|
|
let maxTps: Int
|
|
let jobs: [Job]
|
|
}
|
|
|
|
struct Job: Codable {
|
|
let name: String // Job's name
|
|
private let startAt: String // yyyy-MM-dd HH:mm:ss or HH:mm:ss
|
|
private let endAt: String // yyyy-MM-dd HH:mm:ss or HH:mm:ss
|
|
private let interval: String // 1D, 1H, 1M, 1S
|
|
let weeks: [String] // SUN, MON, TUE, WED, THU, FRI, SAT
|
|
let estimatedTps: Int // Estimated tps for this command
|
|
let command: String // Command line
|
|
|
|
var startDate: Date? {
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
|
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
|
return dateFormatter.date(from: startAt)
|
|
}
|
|
|
|
var intervalTime: TimeInterval {
|
|
let baseSeconds: TimeInterval
|
|
switch interval.suffix(1).uppercased() {
|
|
case "D": baseSeconds = 24 * 60 * 60
|
|
case "H": baseSeconds = 60 * 60
|
|
case "M": baseSeconds = 60
|
|
case "S": baseSeconds = 1
|
|
default: baseSeconds = 0
|
|
}
|
|
guard let time = Int(interval.prefix(interval.utf8.count-1)) else {
|
|
return 0
|
|
}
|
|
return baseSeconds * TimeInterval(time)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class KissBatch {
|
|
|
|
struct TimerJob {
|
|
let name: String
|
|
let timer: Timer
|
|
}
|
|
|
|
var batch: Batch?
|
|
var timers = [TimerJob]()
|
|
var lastBatchFileDate: Date?
|
|
|
|
private let reloadJobName = "__reload_job__"
|
|
|
|
func run() {
|
|
/// Install reloading job
|
|
let timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in
|
|
self.reinstallBatchIfNeeded()
|
|
}
|
|
timers.append(TimerJob(name: reloadJobName, timer: timer))
|
|
timer.fire()
|
|
|
|
/// Wait untile exit signal
|
|
// let semaphore = DispatchSemaphore(value: 0)
|
|
// semaphore.signal()
|
|
// semaphore.wait()
|
|
}
|
|
|
|
private var batchFileUrl: URL {
|
|
URL.currentDirectory().appending(path: "batch.json")
|
|
}
|
|
|
|
private func loadBatch() throws {
|
|
let data = try Data(contentsOf: batchFileUrl, options: .uncached)
|
|
let batch = try JSONDecoder().decode(Batch.self, from: data)
|
|
self.batch = batch
|
|
}
|
|
|
|
private func installBatch() {
|
|
guard let batch = batch else { return }
|
|
for group in batch.groups {
|
|
for job in group.jobs {
|
|
let timer = Timer.scheduledTimer(withTimeInterval: job.intervalTime, repeats: true) { timer in
|
|
self.runJob(job, group: group)
|
|
}
|
|
|
|
timers.append(TimerJob(name: job.name, timer: timer))
|
|
}
|
|
}
|
|
}
|
|
|
|
private func reinstallBatchIfNeeded() {
|
|
do {
|
|
/// Check last save file date
|
|
let lastDate = try FileManager.default.modificationDate(atPath: batchFileUrl.path)
|
|
guard lastBatchFileDate != lastDate else {
|
|
return
|
|
}
|
|
|
|
try loadBatch()
|
|
|
|
removeAllTimers()
|
|
installBatch()
|
|
|
|
lastBatchFileDate = lastDate
|
|
|
|
} catch {
|
|
print(error)
|
|
return
|
|
}
|
|
}
|
|
|
|
private func runJob(_ job: Batch.Job, group: Batch.Group) {
|
|
// NSFileHandle()
|
|
// NSPipe()
|
|
/*
|
|
let task = Process()
|
|
task.launchPath = URL.currentDirectory().path
|
|
task.arguments = [job.command]
|
|
task.standardOutput = outputPipe
|
|
|
|
outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
|
|
|
|
_ = interruptSignal.once {
|
|
if task.isRunning {
|
|
task.interrupt()
|
|
}
|
|
}
|
|
|
|
signal(SIGKILL) { signal in
|
|
print("ending with signal: \(signal)")
|
|
interruptSignal.emit()
|
|
}
|
|
*/
|
|
}
|
|
|
|
private func removeAllTimers() {
|
|
timers.forEach( { $0.timer.invalidate() })
|
|
timers.removeAll()
|
|
}
|
|
}
|
|
|
|
|
|
extension FileManager {
|
|
func modificationDate(atPath path: String) throws -> Date {
|
|
let attributes = try attributesOfItem(atPath: path)
|
|
return attributes[.modificationDate] as! Date
|
|
}
|
|
}
|