Is there a way to schedule a task in ktor? I want to sechedule a task for 20 minutes if they are ove...
i
Is there a way to schedule a task in ktor? I want to sechedule a task for 20 minutes if they are over, that task should be marked expired. Am having idea of using delay but not sure if its tye best approach so far.Any one please?
r
KTOR Server A web server is a very bad system for this as they often terminate long running threads. Clients won’t stay connected etc… You are MUCH better off dropping an entry into a DB and polling it for any that are due and run the code off of that KTOR Client A delay would work fine 🙂
i
Thanks @robert in my case my client is android and thought of centralizing everything on backend. In android i would havenused workmanager but there isn't such in ktor. I guess the delay will work fine.👍
r
In android it would not be ideal to use delay, cause if it went into suspend then delay would suspend. You would get 20min of the app running - not actually 20min. You would need to have a bunch of extra math and logic to deal with that. Android has things like
JobScheduler
built in - I would look at that and not Kotlin/ktor aspects
i
In my case i have my client as android and server as ktor. One user can make a request to another user. If the other user fails to accept or decline the request after 20mins, then that request is marked as expired. I thought of doing it on the backend side. Will that be fine sir?
r
yip, that makes sense. So you absolutely need to do it in the backend, but you can’t just do a delay
i
Any wisdom on it? considering that many requests might be made by other users to different users.
r
exactly what I said before
You are MUCH better off dropping an entry into a DB and polling it for any that are due and run the code off of that
o
That's not correct. You can just go with a coroutine and delay. There is no additional thread involved as the dispatcher will take care of this. So there is no problem with anyone stopping "long running threads".
r
let me know when you googling how to get netty to stop killing your processes cause it times out 😉
even if you solve netty, what happens when your server reboots - if you using ANY cloud provider you can’t control that 100% so anything running will be lost. The DB model is safe and consistent
o
...and complicated. If server reboots are not an issue, such complexity can be avoided. I'm running stuff like this without issues:
Copy code
fun runApplicationServer() {
    embeddedServer(
        Netty,
        port = 8080,
        host = "0.0.0.0",
        module = Application::backendModule
    ).start(wait = true)
}

fun Application.backendModule() {
    val expirationJob = launch {
        delay(20.minutes)
        // do something
    }

    install(ContentNegotiation)
    // ...

    routing {
        // ...
        // Use expirationJob.cancel() to stop a running job and/or restart a new job as required
    }
}
i
Much appreciation guys. @robert i think the Db model is safer. @Oliver.O thanks for coming through.
r
such complexity can be avoided
I think polling a DB is infinitely less complex that trying to get 100% uptime on a single piece of silicon
@Oliver.O your code is spot on, and if I was building a POC I would do the exact same as you are suggesting. I am assuming @IsaacMart needs something more than that
o
As I said: It depends on the requirements. If persistent tasks are a requirement, don't use the above. Otherwise, just do.
i
Thanks @Oliver.O . Have a great time guys.
👍 1
c
if you're on android. long running work should be scheduled using WorkManager
a
Just tuning into this discussion, because I have a similar requirement and I wanted to share how I am doing it. I don't like to run long running tasks and / or polling tasks within ktor. I don't want to deal with the additional error surface. As others have noted, if you get rebooted you have to make sure you can pick up from where you've left etc. What I am doing instead is have a cronjob outside of the backend server. The cronjob periodically calls a dedicated backend route. When this route is hit, it will then check what needs to be done and do it accordingly. So in the DB there is e.g. an expiry timestamp. And if at that moment the backend route is hit by the cronjob, action is taken as necessary. the cronjob is then called as often as is necessary for responsiveness requirements. This way, I just don't have to deal with processes running somehow additionally to the request-response logic provided by ktor. So in a nutshell: • no in-memory timer, but expire timestamp in db • no coroutine stuff in the backend, periodic timer moved to infrastructure • handle work to do as a normal backend route
👍 1
r
couldn’t agree more & absolutely a brilliant approach
i
This is very brilliant @Alexander Weickmann hope this saves someone else also.
1286 Views