Hi all, I’m doing some heavy work on one of my end...
# http4k
a
Hi all, I’m doing some heavy work on one of my endpoints. Is there an easy way to already return a Response, and do the work afterwards?
d
if you're doing this in a singular app, for this you're basically launching a virtual thread and then (typically) retuning an ACCEPTED
a
Hi David, thanks for the response. Are there any examples for virtual threads in http4k? Or should this work out-of-the-box?
d
Well as long as you're on java 21, you should be able to create a standard executor backed by a virtual thread pool and you're good to go. Http4k doesn't need to get involved 🙃
a
Okay, this sounds a lot easier than I thought it would be then 😄 Thanks!
a
Yeah, it's just standard java threading. Launch a thread before returning a response, and you'll be good to go. Often good practice to return a job id so you can look it up afterwards. Something like
Copy code
val jobs = mutableMapOf<UUID, Int>() // use a real database in a production cluster

routes(
    "/jobs" bind Method.POST to {
        val jobId = UUID.randomUUID()
        jobs[jobId] = 1 // queued

        Thread.startVirtualThread {
            jobs[jobId] = 2 // running
            Thread.sleep(1000)
            jobs[jobId] = 3 // done
        }

        Response(Status.ACCEPTED).body(jobId.toString())
    },
    "/jobs/{job_id}" bind Method.GET to { request ->
        val jobId = UUID.fromString(request.path("job_id")!!)
        val status = jobs[jobId]

        if (status == null) {
            Response(Status.NOT_FOUND)
        } else {
            Response(Status.OK).body(status.toString())
        }
    }
)
🙏 1
c
Most web apps grow to a point to have a background/delayed job/task queue. These are usually living in some service that's tailored to that purpose (Redis/RabbitMQ/SQS, but PG also has some primitives lately to support this). Once your web app has this you will probably want to use that for sake of simplicity (one way to do it).
🚀 1
a
Yes, absolutely. You may want to push your background tasks to a queueing system to take advantage of load balancing, visibility, independent scaling, retries, etc. I don't know why I immediately jumped to background threads; maybe because I was working on something that was using background threads at the time.
c
Well there are some usecases for threads, like when you have already prepped some of the data you need to complete all the work during the request cycle, but you just want to do a little more work after responding (like calling some external APIs that may take 0.1-2secs and do not need to be retried). This way you can keep the response fast, but also immediately do what still has to be done.
💯 1