Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share a variable between two routers module in cro?

Tags:

raku

cro

I try to use Cro to create a Rest API that will publish messages in rabbitMQ. I would like to split my routes in different modules and compose them with an "include". But I would like to be able to share the same connection to rabbitMQ in each of those modules too. I try with "our" but it does not work :

File 1:

unit module XXX::YYY;
use Cro::HTTP::Router;
use Cro::HTTP::Server;
use Cro::HTTP::Log::File;
use XXX::YYY::Route1;

use Net::AMQP;

our $rabbitConnection is export = Net::AMQP.new;
await $rabbitConnection.connect;

my $application = route {
        include <api v1 run> => run-routes;
}
...

File 2:

unit module XXX::YYY::Route1;
use UUID;
use Cro::HTTP::Router;
use JSON::Fast;
use Net::AMQP;
my $channel = $XXX::YYY::rabbitConnection.open-channel().result;
$channel.declare-queue("test_task", durable=> True );
sub run-routes() is export { ... }

Error message:

===SORRY!===
No such method 'open-channel' for invocant of type 'Any'

Thanks!

like image 414
STH Avatar asked Oct 19 '18 20:10

STH


2 Answers

When you define your exportable route function you can specify arguments then in your composing module you can create the shared objects and pass them to the routes. For example in your router module :

sub run-routes ($rmq) is export{
    route {
       ... $rmq is available in here
    }
}

Then in your main router you can create your Queue and pass it in when including

my $rmq = # Insert queue creation code here
include product => run-routes( $rmq );

I've not tried this but I can't see any reason why it shouldn't work.

like image 177
Scimon Proctor Avatar answered Nov 17 '22 21:11

Scimon Proctor


The answer by @Scimon is certainly correct, but it does not addresses the OP. On the other hand, the two comments by @ugexe and @raiph are spot-on, so I'll try to summarize them here and explain what's going on.

The error itself

This is the error:

Error message:

===SORRY!=== No such method 'open-channel' for invocant of type 'Any'

It indicates the invocant ($XXX::YYY::rabbitConnection) is of type Any, which is the type usually assigned to variables when they don't have a defined value; that is, basically, $XXX::YYY::rabbitConnection is not defined. It certainly is not since XXX::YYY is not included among the imported modules, as indicated by @ugexe.

The additioal problem indicated by the OP

That module was eliminated from the imported list because, as indicated by the OP

I certainly code it the wrong way because if i try to add use XXX::YYY;, i get a Circular module loading detected error

But of course. since use XXX::YYY::Route1; which is file 2, is included in File 1.

The final solution is to reorganize files

That circular dependence probably points out to the fact that they should be in the same file, or else common code should be factored out to a third file, which would be eventually be included by both. So you should have something like unit module XXX::YYY::Common; use Net::AMQP;

our $rabbitConnection is export = Net::AMQP.new;
await $rabbitConnection.connect;

And then

use XXX::YYY::Common;

in both modules.

like image 26
jjmerelo Avatar answered Nov 17 '22 21:11

jjmerelo