Closed d5ve closed 1 year ago
I guess it comes down to it working OK, as long as the cron script only use()
s packages which don't use Dancer2::Plugin::Deferred;
either directly or indirectly.
Actually it is a good idea to separate the business logic from the Dancer2 app itself IMHO. In my projects the business logic is usually covered by a DBIx::Class schema and other modules/role outside of the Dancer2 app.
Aside from that which plugins do you use in your app?
@d5ve seconding what @racke is saying here. You'd be better served by putting code that is used in Dancer2 and cron scrips in some sort of model layer, be it DBIx::Class objects, or one or Moo(se) objects that encapsulate that object. Not only is the code more usable in more situations, but it is significantly easier to test.
Does cron need to output HTML, or data, or neither?
Thanks for the suggestions, and sorry for the delay responding.
The cron scripts in question generate and send HTML emails based on various events in the database. For example emailing a website admin a summary view of what's coming up for them next week.
I am use
ing Dancer2 in the scripts for a few reasons: it gives access to the Dancer2 DSL like template()
, schema()
, and email()
; it reads from the same config file as the webserver, so there is only one place to change DB connection strings, SMTP config, and other settings; it allows easy reuse of existing website business logic, template and partial templates to generate the HTML email contents.
I know I can do all the above "manually", but Dancer2's lovely DSL has made me lazy and contented. I've also eyed up having the cron script make actual HTTP requests to the webserver itself to generate the email message HTML, however then I'd need to worry about security/cookies/sessions etc.
Thanks for explaining your use case better. I understand your "why" better now, but it's not a use that we necessarily constructed Dancer2 for.
That being said, we might be able to help you navigate some of that with some adjustments to your app. I do not, unfortunately, have the tuits for it right now. I'm leaving this open in case others would like to chime in, and as a reminder to myself to come back to this.
Thanks for being such a fan, and for wanting to use Dancer2 in All The Things :)
I feel dirty even suggesting this, however:
You could look at something like Module::Runtime
to conditionally load Dancer2::Plugin::Deferred
when run from the web, and not from cron. We have an example of it in our cookbook (though not exactly the way you'd use it), or look at the docs for Module::Runtime
.
I do not officially endorse this solution. It may not even work. But it's a possible route to explore.
Good luck!
Love it, thanks @cromedome!
I was wondering about something even more hacky - monkey-patching a dummy Request object in there somehow. With (digging myself even deeper into a hole) a bit of autoload magic to have it not fall over when random methods are called.
This question is well and truly answered, thanks both, and all further madness will be confined to my codebases.
I have a Dancer2 app with the route handler functions spread around various packages. These packages all have a stanza of
use Dancer2 appname => 'App::Totally::Awesome';
which imports the dancer2 DSL, and uses the same runner for all the different packages.I'd like to
use()
some of those packages in a cron scripts which sends emails. The email bodies are generated by calls to the dancer2 DSL'stemplate()
If I
use App::Totally::Awesome::HighFive;
in the cron script, then callingtemplate()
in the script gives the error below:This error is where a function in
Deferred.pm
is calling$plugin->app->request->var()
andrequest()
is undefined.This error also happens if the cron script itself has a
use Dancer2 appname => 'App::Totally::Awesome';
stanza.However, the cron script, and the call to
template()
work if the script has a bareuse Dancer2;
, where noappname
is specified (so I think the runner is calledmain
). But only as long as the script doesn't include any of the handler packages.I'd like the script to be able to
use()
some packages from the app, as they contain useful business logic that I don't want to duplicate in the script itself.How can I do this?
Cheers.