Are there any issues around creating a timer in the context of a request in Vapor? I need to trigger an action that takes place several minutes after a user initiates a process. So far, when I call the routine that does this, I get confirmation that the code that sets up the timer has run. But neither the timer, nor a call to the main DispatchQueue ever fires. The method that calls the setup redirects the user immediately afterwards to another endpoint, and I'm wondering if this is why.
func startTournament(req: Request) -> EventLoopFuture<Response> {
let uId : UUID = req.auth.get(User.self)!.id!
var tourn : Tournament?
return User.query(on: req.db)
.with(\.$tournament) { $0.with(\.$invitations)}
.filter(\.$id == uId)
.first().flatMap { u in
tourn = u!.tournament!
Tournament.addTournamentTimer(tourn!)
is the code where the setup is called.
This is the method called, and the print statement executes:
static func addTournamentTimer(_ tourn : Tournament) {
DispatchQueue.main.asyncAfter(deadline: .now() 5) {
print("Timer fired!")
}
let timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { timer in
print("Timer fired!")
}
print("adding timer for tournament \(tourn.name)")
}
I don't want to use the DispatchQueue approach, but I tried including it to see if it worked. It doesn't seem to. I'm fairly new to using timers, but I have a fair number of functions that work on timers in a client app, so I'm quite able to figure them out elsewhere. Again, I'm assuming this is something not clear to me about asynchronous requests, and or the timer getting dumped when the redirect happens?
CodePudding user response:
The right way to set a timer on server-side is to use NIO instead of GCD.
Take an eventLoop
and check its schedule...
methods to choose the right one for your situation.
Here is an example of your method with NIO:
static func addTournamentTimer(_ tourn : Tournament, on req: Request) {
req.eventLoop.scheduleTask(deadline: NIODeadline.now() .seconds(5)) {
print("Timer fired!")
}
print("adding timer for tournament \(tourn.name)")
}