I’m working on a simple “web” server (to be run only locally) which allows other programs running locally to request solutions to optimization problems.
Firstly, and most importantly, solving these optimization problems can take a prohibitively long time. If an optimization problem runs for too long, it’s best to just give up on it.
Question 1: What’s the idiomatic way to start a job (be it via @async
or @spawn
or something else) and wait until either that job is completed or a certain amount of time has elapsed, aborting the job if it has not completed in time?
I see two ways, both of which feel clunky and therefore likely wrong:
-
Have the master process start the job, e.g. with
@spawn
, and then sleep in short chunks. In each wake between sleeps, check of the job is completed and if so exit the sleep loop; also exit the loop if the total sleep time exceeds the limit. -
Have the master process wait on a
Condition
. The worker process triggers the condition when work is complete, and an additional process sleeps the allotted amount of time before triggering the condition.
Either way, a long-running job is aborted with Base.interrupt
?
I have a simple version using HttpServer
running with approximately the following code:
using HttpServer
function process_request(req::Request, res::Response)
x = extract_data_from_request
y = solve_optimization_problem(x) # takes a few seconds
return Response(200, answer_to_json(y))
end
server = Server(process_request)
run(server, 8000)
This works well as long as requests aren’t coming in too fast, at which point things really slow down. I’ve tried code like the following, which seems to help.
@everywhere function solve_optimization_problem(x) ...
function process_request(req::Request, res::Response)
x = extract_data_from_request
y = @fetch solve_optimization_problem(x)) # takes a few seconds
return Response(200, answer_to_json(y))
end
server = Server(process_request)
run(server, 8000)
Question 2: is this the ‘right’ way?
Intuitively, it seems like we want the master process to be able to say to a worker “you answer this request,” which would free the master up for other requests; the master never has to revisit the current request. Something like
@everywhere function optimize_and_package(x)
y = solve_optimization_problem(x)
return Response(200, answer_to_json(y))
end
function process_request(req::Request, res::Response)
x = extract_data_from_request
@return_when_complete @spawn optimize_and_package(x)
end
Question 3: Is there a way to do this / is it even desirable?
Preemptive thanks for the help!