Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Dancer2: respond to client while making its own async call

by stevieb (Canon)
on Apr 01, 2021 at 17:25 UTC ( [id://11130680]=perlquestion: print w/replies, xml ) Need Help??

stevieb has asked for the wisdom of the Perl Monks concerning the following question:

Greetings and good day my fellow esteemed Monks.

I come today with a Dancer2 and simultaneous asynchronous request question(s). I have a microcontroller (Wemos D1 mini with an ESP8266 chip) in my garage that presents data about my Tesla vehicle state on an OLED screen and a strip of LEDs. Here's how it works:

  • Microcontroller calls REST API on a Raspberry Pi to get vehicle data every two seconds while there's motion in garage
  • Raspberry Pi fetches vehicle data from Tesla API
  • Raspberry Pi sends updated data back to microcontroller
  • Microcontroller presents status to user

What I want to have happen, is something like this:

  • Microcontroller requests data from Raspberry Pi every two seconds if there is motion in garage
  • Raspberry Pi sends an async request to Tesla API for updated data, but while waiting, sends back last known data (I'll set an expiry)
  • Microcontroller presents status to user

Essentially, I want the Pi to asynchronously request data from Tesla's API about my vehicle, respond with the last (global) poll data before the current (Tesla API) request is done (effectively terminating the HTTP connection), then update the global variable that contains the vehicle data when the async Tesla API call is complete for the next microcontroller call.

How can I respond back to the microcontroller with previous data before the current Tesla API call is completed?

Also, how can I ensure that if the first async Tesla API call is done before spawning off a second one (ie. if two seconds have elapsed and a new microcontroller check comes in and the async process isn't finished from last time), respond with the existing data without respawning a new async process?

  • Comment on Dancer2: respond to client while making its own async call

Replies are listed 'Best First'.
Re: Dancer2: respond to client while making its own async call
by 1nickt (Canon) on Apr 01, 2021 at 21:10 UTC
Re: Dancer2: respond to client while making its own async call
by stevieb (Canon) on Apr 01, 2021 at 19:33 UTC

    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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11130680]
Approved by marto
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (3)
As of 2024-04-19 19:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found