Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScheduledJob management [Draft] #74

Open
maximkrouk opened this issue Jun 8, 2020 · 3 comments
Open

ScheduledJob management [Draft] #74

maximkrouk opened this issue Jun 8, 2020 · 3 comments
Labels
enhancement New feature or request

Comments

@maximkrouk
Copy link

Now it's not possible to edit the schedule of a job or to remove a job from the queue.

@jdmcd
Copy link
Member

jdmcd commented Jun 10, 2020

Just to make sure I'm understanding the question right, are you talking about scheduling a new job on the fly, not at startup? If so, then yes, I don't believe that's possible right now since we capture all of the scheduled jobs on startup.

@maximkrouk
Copy link
Author

maximkrouk commented Jun 10, 2020

Yep, I mean on the fly. Probably there is already a workaround: app.queues.schedule() can accept a builder, which can be stored in app.storage for example and probably can be used to change the job schedule. Also, a wrapper-job with optional action or some sort of flag can be implemented by the user and be stored too to fulfill a need to stop/continue the execution.
It's not very convenient to store multiple objects for the management of one job. So the user can create another wrapper. I'm not sure, but I'll try to use something like this

import Queues
import Vapor

extension Application.Queues {
    func schedule(_ task: Task) -> TaskContainer { .init(task, schedule(task)) }
}

final class TaskContainer {
    let execute: ScheduleBuilder
    let task: Task
    init(_ task: Task, _ scheduleBuilder: ScheduleBuilder) {
        self.task = task
        self.execute = scheduleBuilder
    }
    
    func store(in variable: inout TaskContainer) {
        variable = self
    }
    
    func store<Key: StorageKey>(in storage: inout Storage, forKey key: Key.Type)
    where Key.Value == TaskContainer {
        storage[key] = self
    }
}

final class Task: ScheduledJob {
    private var _action: (() -> Void)?
    private let lock: Lock = .init()
    
    private init(action: (() -> Void)?) {
        self._action = action
    }
    
    init(action: @escaping () -> Void) {
        self._action = action
    }
    
    func cancel() {
        lock.withLock {
            self._action = .none
        }
    }
    
    func `override`(with task: Task) {
        lock.withLock {
            self._action = task._action
        }
    }
    
    @inlinable
    func run(context: QueueContext) -> EventLoopFuture<Void> {
        _action?()
        return context.eventLoop.future(())
    }
    
    @inlinable
    static func empty() -> Task { .init(action: .none) }
}

and if it works maybe it would be nice to have some kind of manager object out-of-the-box. 🌚

Usage

// initial setup

app.queues
    .schedule(.sendPushnotifications(app))
    .store(in: &app.storage, forKey: Task.StorageKeys.SendPushNotifications.self)
    .execute.weekly().on(.monday).at(.noon)

// edits

app.storage[Task.StorageKeys.SendPushNotifications.self].map { container in
    container.execute.minutely().at(0)
}

app.storage[Task.StorageKeys.SendPushNotifications.self].map { container in
    container.task.cancel()
}

app.storage[Task.StorageKeys.SendPushNotifications.self].map { container in
    container.task.override(with: .sendPushNotifications(app))
}

@tanner0101 tanner0101 added the enhancement New feature or request label Jul 13, 2020
@3a4oT
Copy link
Contributor

3a4oT commented Jul 16, 2020

+1 for this functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants