With Mojo::IOLoop's delay, timer, and recurring, can I use them in a promises's "then" clause?

175 views
Skip to first unread message

Gordon Dollarnanda

unread,
Sep 25, 2020, 3:08:01 AM9/25/20
to Mojolicious
hi, guys,

 Been reading up 
and a few threads in the group.

Apologies if i had missed this in advance but with Mojo::IOLoop's delay, timer, and recurring, can I use them in a promises's "then" clause? 
 I am trying to do that to no avail.

 For example, in the following code snippet,  the test runs very quickly and doesn't delay at all.

Output:

[16:50:12] anexiole:server git:(bugfix/ET750-asyncTests*) $ prove -v t/api/fwm/job/up.t 
t/api/fwm/job/up.t .. 
[info] Setting log level to: debug
[info] Manager started: MG EMU: Mojo::Server::Daemon
[info] Worker started: MG EMU: [27346]
[info] Manager started: MG EMU: Mojo::Server::Daemon
[info] Worker started: MG EMU: [27346]
 Current port of t is 50016
 RESULTS : $VAR1 = '{"jobId":2530,"task":"upgrade"}';
job id is 2530
Get the job out ...
IOLOoP is active
After the ioloop...
1..0
skipped: (no reason given)



Snippet:



           my $data = from_json( $test_scenario->{contents}->{data} );

            my $enqueue_job = Mojo::URL->new($url);

            $enqueue_job->query(
                Mojo::Parameters->new(
                    'format'     => $test_scenario->{'contents'}->{'format'},
                    'scope'      => $scope,
                    'deviceType' => $data->{'deviceType'},
                    'data'       => $test_scenario->{'contents'}->{'data'},
                )
            );
            print STDERR qq{ Current port of t is }
                . $t->ua->server->url->port . qq{\n};

            $t->ua->post_p( $enqueue_job => $header )->then(
                sub ($tx) {
                    print STDERR qq{ RESULTS : }
                        . Dumper( $tx->result->body );
                    my $job_id = from_json( $tx->result->body )->{'jobId'};
                    print STDERR qq{job id is $job_id\n};

                    # Grab the report of the job out
                    my $retrieve_enqueued_job_url
                        = Mojo::URL->new(qq{/myTestApp/api/job/v12/result/$job_id});
                    $retrieve_enqueued_job_url->query(
                        Mojo::Parameters->new( 'format' => q{json}, ),
                    );
                    print STDERR qq{Get the job out ...\n};

                    if ( $t->ua->ioloop->is_running() ) {
                        print STDERR qq{IOLOoP is active\n};
                    }
                    else {
                        print STDERR qq{IOLOoP is not active\n};
                    }
                    use Mojo::IOLoop::Delay;
                    my $delay = Mojo::IOLoop->delay(
                        sub ($delay) {
                            Mojo::IOLoop->timer( 3 => $delay->begin );
                        },
                        sub ($delay) {
                            print STDERR '3 seconds';
                            Mojo::IOLoop->timer( 3 => $delay->begin );
                        },
                        sub ($delay) {
                            print STDERR '6 seconds';
                            Mojo::IOLoop->timer( 3 => $delay->begin );
                        },
                        sub ($delay) { print STDERR '9 seconds'; }
                    );
                    $delay->wait;

                    $t->ua->get_p( $retrieve_enqueued_job_url => $header )->then(
                        sub ($tx) {
                            print STDERR qq{ the job RESULTS : }
                                . Dumper( $tx->result->body );
                        }
                    );

                    print STDERR qq{After the ioloop...\n};

                }
            )->catch(
                sub (@errors) {
                    print STDERR qq{Job retrieval errors: } . Dumper(@errors);
                }
            )->wait;
    }


Thank you

Gordon Yeong.


Gordon Dollarnanda

unread,
Sep 25, 2020, 3:15:48 AM9/25/20
to Mojolicious
Apologies-  i hit the "send" button a bit too quickly.

The test script works this way:

1. enqueue a new job by calling a given endpoint api. A Test::Mojo instance is instantiated. Assume the port is 51611. This is done with a promise using $t->ua->post_p(...) where $t is a Test::Mojo.
2. the job will be picked up by a minion service running in the background. The newly enqueued job's id is recorded.
3. this is when i need a delay or a recurring loop because the job's argument will have another endpoint url (with the same port currently used by my current Test::Mojo instance) which uses the same port , 51611
4. after the job runs, the results of the run is going to be stored in the Minion's job under results (ie $minion->info->{'result'}). 
5. a call to another API endpoint to retrieve the results of the job (of the job id in step 2).
6. Will test for the job result's values against my expected values (part of Test::More).

Step 3 is the reason for me to want to plant a delay in the 'then()' section of the promise in step 1.
simple.t

Heiko Jansen

unread,
Sep 30, 2020, 9:15:20 AM9/30/20
to Mojolicious
I actually don't know about any pitfalls when using Mojo::IOLoop's delay etc. methods within "then" clauses, but
from my (limited) experience I'd suggest to avoid mixing traditional IOLoop methods and promises if only
because it makes it even harder to follow the code flow.

To me it looks like you're just trying to kill some time when you using the Mojo::IOLoop->delay() construct in the
snippet in your first post?
If so, I believe something along these lines should work (note: I just typed that here and did not test it):

    print STDERR qq{Get the job out ...\n};
    return Mojo::Promise->timer(3);
} )->then( sub {
    print STDERR '3 seconds'; 
    return Mojo::Promise->timer(3);
} )->then( sub {
    print STDERR '6 seconds'; 
    return Mojo::Promise->timer(3);
} )->then( sub {
    print STDERR '9 seconds'; 
    $t->ua->get_p( $retrieve_enqueued_job_url => $header )
} )->then(
    sub ($tx) {
          print STDERR qq{ the job RESULTS : }
                 . Dumper( $tx->result->body );
    }
);

Declaration of the variables $retrieve_enqueued_job_url  and  $header would have to be lifted outside the
first "then" clause, of course, to be available in the later ones.

I hope that actually works and helps you move forward... ;-)
Reply all
Reply to author
Forward
0 new messages