Skip to content

Commit

Permalink
feat: adding pause rate limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
iloveitaly committed Dec 29, 2023
1 parent 5f49dce commit 6f95693
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 3 deletions.
1 change: 1 addition & 0 deletions Sources/hyper-focus/hyper_focus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct SwitchingActivity: CustomStringConvertible {

struct Configuration: Codable {
struct ScheduleItem: Codable, Equatable {
var pause_limit: Int?
var start: Int?
var start_minute: Int?
var end: Int?
Expand Down
31 changes: 31 additions & 0 deletions Sources/hyper-focus/rate_limiter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation

class RateLimiter {
private var timestamps: [String: [Date]] = [:]

// actions per hour
var limit: Int?

func allowed(type: String) -> Bool {
if limit == nil {
debug("no limit set, allowing action '\(type)'")
return true
}

let now = Date()
let oneHourAgo = now.addingTimeInterval(-3600)

var typeStamps = timestamps[type, default: []]
typeStamps = typeStamps.filter { $0 > oneHourAgo }

if typeStamps.count < limit! {
typeStamps.append(now)
timestamps[type] = typeStamps
return true
}

// Update the timestamps to remove stale entries
timestamps[type] = typeStamps
return false
}
}
14 changes: 13 additions & 1 deletion Sources/hyper-focus/schedule_manager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

class ScheduleManager {
var configuration: Configuration
var pauseLimiter = RateLimiter()

var schedule: Configuration.ScheduleItem?
var endOverride: Date?
Expand Down Expand Up @@ -83,9 +84,15 @@ class ScheduleManager {
}
}

func pauseBlocking(_ end: Date) {
func pauseBlocking(_ end: Date) -> Bool {
if !pauseLimiter.allowed(type: "pause") {
error("pause limit reached, not pausing")
return false
}

log("pause blocking until \(end)")
endPause = end
return true
}

func resumeBlocking() {
Expand Down Expand Up @@ -122,6 +129,11 @@ class ScheduleManager {
// TODO: there's probably some race condition risk here, but I'm too lazy to understand swift concurrency locking
self.schedule = schedule

if schedule != nil {
// we want to set limit to nil if not set in schedule
pauseLimiter.limit = schedule!.pause_limit
}

if schedule != nil, schedule!.start_script != nil {
TaskRunner.executeTaskWithName(schedule!.start_script!, "start_script")
}
Expand Down
7 changes: 5 additions & 2 deletions Sources/hyper-focus/server.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,12 @@ class ApiServer {

// convert pauseUtil to date
let untilDate = Date(timeIntervalSince1970: TimeInterval(pauseUtil!))
self.scheduleManager.pauseBlocking(untilDate)

return ["status": "ok"]
if self.scheduleManager.pauseBlocking(untilDate) {
return ["status": "ok"]
} else {
return ["status": "error", "message": "blocked"]
}
}

try! server.start()
Expand Down
3 changes: 3 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
"name": {
"type": "string"
},
"pause_limit": {
"type": "number"
},
"schedule_only": {
"type": "boolean"
},
Expand Down

0 comments on commit 6f95693

Please sign in to comment.