http://qs1969.pair.com?node_id=11130686


in reply to Dancer2: respond to client while making its own async call

I figured it out, using one of my own CPAN distributions no less. I updated my Async::Event::Interval software to accept an "interval" of zero, which instead of looping every N seconds, simply runs a single time. So when the Dancer2 route is called, it'll spin off an external event to fetch and update the data, and then I can return existing data if it exists immediately while the background task is still working.

The software also already has a built-in check to see if the event is still running or not. Here's a minimal demo:

use warnings; use strict; use Async::Event::Interval; use IPC::Shareable; my $data; tie $data, 'IPC::Shareable', 'TSLA', {create => 1, destroy => 1}; $data = '{"charge": 85}'; my $event = Async::Event::Interval->new(0, sub {$data = '{"charge": 10 +0}'}); print "$data\n"; $event->start; print "Main program continues...\n"; print "Background event still running...\n" if $event->status; sleep 1; print $event->status == -1 ? "Event stopped\n" : "Event running\n"; print "$data\n";

Output:

{"charge": 85} Main program continues... Background event still running... Event stopped {"charge": 100}

Since the Dancer2 app is always running, I just make the event itself along with the data string (JSON) global, and use IPC::Shareable (which I have CO-MAINT to) to share the data between the processes. The Dancer2 route just calls $event->start if $event->status != -1;, and can then return back to the calling microcontroller immediately while the updater event runs as a separate proc.