FAQ
Good evening,

First, I may not be approaching this the right way at all. So
I'm happy to take any suggestions for a better way to do what I need.

I've got a daily task (cron job currently) which sends emails to
users. I want to use existing TT templates to generate the email
content. I'm using Mail::Builder::Simple for the message
creation & sending.

All the simple tests are working fine, until I want to use the
existing template setup that I've been using to send email from
within Catalyst. Specifically, the wrapper template (with
header, footer, etc) makes fairly extensive use of c.uri_for and
c.uri_for_action. And of course the Catalyst context is not
available from the cron job (at least no way that I could find).

One option is to move all the logic to a controller action and
just have the cron job make an http request. That doesn't seem
like the right approach though.

Does anyone have suggestions on how I can use my existing
template structure and still be able to use `c` from a cron job?
Or should I use a completely different approach?

Thanks,
Charlie

--
? Charlie Garrison ? <garrison@zeta.org.au>

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
? http://www.ietf.org/rfc/rfc1855.txt

Search Discussions

  • Jon Schutz at Apr 11, 2011 at 1:04 am
    Perhaps fire up your app from the cron job using
    Catalyst::Engine::Embeddable?

    --

    Jon Schutz
    http://notes.jschutz.net
    On 10/04/11 22:40, Charlie Garrison wrote:
    Good evening,

    First, I may not be approaching this the right way at all. So I'm
    happy to take any suggestions for a better way to do what I need.

    I've got a daily task (cron job currently) which sends emails to
    users. I want to use existing TT templates to generate the email
    content. I'm using Mail::Builder::Simple for the message creation &
    sending.

    All the simple tests are working fine, until I want to use the
    existing template setup that I've been using to send email from within
    Catalyst. Specifically, the wrapper template (with header, footer,
    etc) makes fairly extensive use of c.uri_for and c.uri_for_action. And
    of course the Catalyst context is not available from the cron job (at
    least no way that I could find).

    One option is to move all the logic to a controller action and just
    have the cron job make an http request. That doesn't seem like the
    right approach though.

    Does anyone have suggestions on how I can use my existing template
    structure and still be able to use `c` from a cron job? Or should I
    use a completely different approach?

    Thanks,
    Charlie
  • Charlie Garrison at Apr 11, 2011 at 9:00 am
    Good evening,

    On 11/04/11 at 10:34 AM +0930, Jon Schutz
    wrote:
    Perhaps fire up your app from the cron job using
    Catalyst::Engine::Embeddable?
    Thanks, didn't know about that one; I'll have a look.

    Hmm, the documentation is a bit sparse; I can't see how to get
    $c (or $app). I can't see anything in the test files either
    which show how to get the app object. Do you have an example you
    could share?

    Or should I just start the embeddable instance and then do a
    handle_request to process the email sending?

    Thanks,
    Charlie

    --
    ? Charlie Garrison ? <garrison@zeta.org.au>

    O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
    ? http://www.ietf.org/rfc/rfc1855.txt
  • Jon Schutz at Apr 11, 2011 at 11:50 am

    On 04/11/2011 06:30 PM, Charlie Garrison wrote:
    Good evening,
    On 11/04/11 at 10:34 AM +0930, Jon Schutz wrote:

    Perhaps fire up your app from the cron job using
    Catalyst::Engine::Embeddable?
    Thanks, didn't know about that one; I'll have a look.

    Hmm, the documentation is a bit sparse; I can't see how to get $c (or
    $app). I can't see anything in the test files either which show how to
    get the app object. Do you have an example you could share?

    Or should I just start the embeddable instance and then do a
    handle_request to process the email sending?
    That was my thought. Usage is essentially...

    use strict;
    use warnings;
    use HTTP::Request;

    BEGIN {
    $ENV{CATALYST_ENGINE} = 'Embeddable';
    }

    require MyApp;
    my $response;
    MyApp->handle_request(HTTP::Request->new('GET',
    'http://localhost/send/email'), \$response);
  • Matthias Dietrich at Apr 11, 2011 at 2:34 pm
    Hi,

    Am 11.04.2011 um 13:50 schrieb Jon Schutz:
    MyApp->handle_request(HTTP::Request->new('GET',
    'http://localhost/send/email'), \$response);
    never used this module, but be careful: Catalyst looks at the URL you are calling the app, so all your links may point to localhost within your mail with this example.

    Sorry, don't have a better approach than calling the app with a request, but I'm also interested in solutions to this!

    Matthias

    --
    rainboxx Software Engineering
    Matthias Dietrich

    rainboxx Matthias Dietrich | Phone: +49 7141 / 2 39 14 71
    K?nigsallee 43 | Fax : +49 3222 / 1 47 63 00
    71638 Ludwigsburg | Mobil: +49 151 / 50 60 78 64
    CPAN: http://search.cpan.org/~mdietrich/
    XING: https://www.xing.com/profile/Matthias_Dietrich18
    GULP: http://www.gulp.de/profil/rainboxx.html
  • Octavian Rasnita at Apr 11, 2011 at 3:58 pm
    From: "Charlie Garrison" <garrison@zeta.org.au>
    Good evening,

    First, I may not be approaching this the right way at all. So
    I'm happy to take any suggestions for a better way to do what I need.

    I've got a daily task (cron job currently) which sends emails to
    users. I want to use existing TT templates to generate the email
    content. I'm using Mail::Builder::Simple for the message
    creation & sending.

    All the simple tests are working fine, until I want to use the
    existing template setup that I've been using to send email from
    within Catalyst. Specifically, the wrapper template (with
    header, footer, etc) makes fairly extensive use of c.uri_for and
    c.uri_for_action. And of course the Catalyst context is not
    available from the cron job (at least no way that I could find).

    One option is to move all the logic to a controller action and
    just have the cron job make an http request. That doesn't seem
    like the right approach though.

    Does anyone have suggestions on how I can use my existing
    template structure and still be able to use `c` from a cron job?
    Or should I use a completely different approach?

    Thanks,
    Charlie



    Hi Charlie,

    The TT templates used by the Catalyst app might contain many things like c.user, c.uri_for_action, may display images, may depend on other templates which are loaded automaticly when those templates are specified in the app config file. So there is no sane way of using those wrapper templates for sending email from a cron job.
    When you send a picture included in the email message you may want to embed it and not let the email message access it on your web server. Also, the Catalyst context depend on the request, so you'll need to make a web request in order to have the same context variable and it would affect much the performance if you'll load the Cat app just for sending email. You can do it this way, but... it isn't a way I prefer to do this thing.

    Whenever you will find that a template used in the Cat app can't be used in a cron job, split that template into smaller templates, and for the templates that use the Catalyst context create another version that doesn't use it. Then make a template that include those templates which work in the Cat app and another template that works in the cron job.

    This way, the Cat app and the standalone program will share those templates they can share, and there won't be dupplicate templates, but there won't be any problems with those parts of the templates that use the Catalyst context.

    You need to use the same approach you use whenever you find that you need to use a part of a template into another template... extract it as a separate template and include it in both templates with INCLUDE or PROCESS.

    If there are too many parts of the template that needs to be changed, it is a better idea to create a separate entire template for using it in the external program. The alternative of sharing the templates among the Cat app and other external program would involve using templates that don't depend on the Catalyst app, and this can be done easily, but we would miss many features offered by the Catalyst context, and we probably need to share too few templates to prefer to lose those features.

    Octavian
  • Charlie Garrison at Apr 11, 2011 at 10:40 pm
    Good morning,

    On 11/04/11 at 9:20 PM +0930, Jon Schutz
    wrote:
    That was my thought. Usage is essentially...

    use strict;
    use warnings;
    use HTTP::Request;

    BEGIN {
    $ENV{CATALYST_ENGINE} = 'Embeddable';
    }

    require MyApp;
    my $response;
    MyApp->handle_request(HTTP::Request->new('GET',
    'http://localhost/send/email'), \$response);
    Thanks for clarifying. And other than not tying up a FastCGI
    process, what is the advantage of that approach over just
    sending a request via http?

    Thanks,
    Charlie

    --
    ? Charlie Garrison ? <garrison@zeta.org.au>

    O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
    ? http://www.ietf.org/rfc/rfc1855.txt
  • Charlie Garrison at Apr 11, 2011 at 11:50 pm
    Good morning,

    On 11/04/11 at 6:58 PM +0300, Octavian Rasnita
    wrote:
    The TT templates used by the Catalyst app might contain many things
    like c.user, c.uri_for_action, may display images, may depend on other
    templates which are loaded automaticly when those templates are
    specified in the app config file. So there is no sane way of using
    those wrapper templates for sending email from a cron job.
    That was the conclusion I was reaching; I wanted feedback from
    others before I tried to make my own garden path.
    ....so you'll need to make a web request in order to have the same
    context variable and it would affect much the performance if you'll
    load the Cat app just for sending email. You can do it this way, but...
    it isn't a way I prefer to do this thing.
    Being a daily cron job, loading the app once isn't too much of
    an issue. But I couldn't really see what the advantage was
    either. All my other cron jobs have been able to use models only
    (DBIC), and I was thinking I could just use TT outside Catalyst
    as well, but I hadn't thought through all the ctx dependancies
    in the templates.
    Whenever you will find that a template used in the Cat app can't be
    used in a cron job, split that template into smaller templates, and for
    the templates that use the Catalyst context create another version that
    doesn't use it. Then make a template that include those templates which
    work in the Cat app and another template that works in the cron job.
    Or find all uses of ctx in the templates and supply sane values
    (or methods) in template_vars to replace the standard Catalyst
    ctx. That seems like a maintenance nightmare though.
    If there are too many parts of the template that needs to be changed,
    it is a better idea to create a separate entire template for using it
    in the external program.
    I'll consider this idea. Since it's just email templates they
    are not as complex. I'm not sure what the benefit will be
    though. Except for not having to take a FastCGI process, I can't
    see what the benefit of a 'smart' cron job is. I may as well
    just send a http request to the app.

    I seem to recall a few cron/schedule packages to use within Cat
    apps. The only one I can find right now is
    Catalyst::Plugin::Scheduler, which I don't really care for since
    it just piggybacks on user requests. Can anyone suggest any others?
    The alternative of sharing the templates among the Cat app and other
    external program would involve using templates that don't depend on the
    Catalyst app, and this can be done easily, but we would miss many
    features offered by the Catalyst context, and we probably need to share
    too few templates to prefer to lose those features.
    Yep, I agree. I can certainly do it all outside Cat context, but
    not sure it's worth the maintenance headache. So unless someone
    else comes up with clever suggestion I'll just move all the
    logic to a controller action.

    Which just leaves whether to use a scheduler within Catalyst, or
    just have a cron job send a request. Are there any best
    practices for that I should be aware of?

    Thanks,
    Charlie

    --
    ? Charlie Garrison ? <garrison@zeta.org.au>

    O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
    ? http://www.ietf.org/rfc/rfc1855.txt
  • Jon Schutz at Apr 12, 2011 at 12:05 am

    On 12/04/11 08:10, Charlie Garrison wrote:
    Good morning,
    On 11/04/11 at 9:20 PM +0930, Jon Schutz wrote:

    That was my thought. Usage is essentially...

    use strict;
    use warnings;
    use HTTP::Request;

    BEGIN {
    $ENV{CATALYST_ENGINE} = 'Embeddable';
    }

    require MyApp;
    my $response;
    MyApp->handle_request(HTTP::Request->new('GET',
    'http://localhost/send/email'), \$response);
    Thanks for clarifying. And other than not tying up a FastCGI process,
    what is the advantage of that approach over just sending a request via
    http?
    Depends on your circumstances, and personally I'd probably take the
    approach of divorcing the templates from the catalyst context and just
    use TT outside of Catalyst. But potential advantages of the embedded
    approach are:

    * Not needing to expose private URLs - if the URL you need to hit to
    generate the email is not supposed to be available to the outside world,
    you can use a different configuration for the app controlled from the
    cron job.
    * Still works if your Apache/FastCGI happen to be not running, in the
    midst of restarting, or in bad shape for whatever reason, so save a
    range of error checking and recovery that you would otherwise have to do.
    * Can send your emails from another machine even if you don't have an
    app running there.

    BTW, you can use whichever form of URL that you like in the embedded
    request - all of these forms that I tried still work (though as Matthias
    pointed out, may affect how URLs appears in your templated output):

    http://my.domain.com/send/email
    http:///send/email
    /send/email
  • Peter Edwards at Apr 12, 2011 at 1:06 am

    On 12 April 2011 00:50, Charlie Garrison wrote:

    Good morning,

    On 11/04/11 at 6:58 PM +0300, Octavian Rasnita wrote:

    The TT templates used by the Catalyst app might contain many things
    like c.user, c.uri_for_action, may display images, may depend on other
    templates which are loaded automaticly when those templates are
    specified in the app config file. So there is no sane way of using
    those wrapper templates for sending email from a cron job.
    That was the conclusion I was reaching; I wanted feedback from others
    before I tried to make my own garden path.
    Put the logic in a model class that reads a config shared with but
    independent from your controller so you can run it outside of Catalyst.
    This article outlines how to do this
    http://www.catalystframework.org/calendar/2007/14
    If you need any web transaction details (c.user etc.) capture them at
    request time and put them in an item in a queue (using ActiveMQ or similar).
    Then in your cron script step through the queue entries, unpack the details
    and do the template merge using TT2 before sending using Mail::Sender or
    Email::Stuff or whatever.
    You don't really need the Catalyst controller framework up and running to do
    that.

    Regards, Peter
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20110412/c2f77931/attachment.htm
  • Octavian Rasnita at Apr 12, 2011 at 5:53 am
    From: Peter Edwards
    On 12 April 2011 00:50, Charlie Garrison wrote:

    Good morning,

    On 11/04/11 at 6:58 PM +0300, Octavian Rasnita wrote:


    The TT templates used by the Catalyst app might contain many things
    like c.user, c.uri_for_action, may display images, may depend on other
    templates which are loaded automaticly when those templates are
    specified in the app config file. So there is no sane way of using
    those wrapper templates for sending email from a cron job.


    That was the conclusion I was reaching; I wanted feedback from others before I tried to make my own garden path.


    Put the logic in a model class that reads a config shared with but independent from your controller so you can run it outside of Catalyst.
    This article outlines how to do this http://www.catalystframework.org/calendar/2007/14

    At the top of that article appears:

    "UPDATE: As of 2008, there is a new module which avoids the "kludgy" solution mentioned below: Config::JFDI."

    At a certain moment, Config::JFDI started to support "__path_to()".

    The problem is not the model only, but the templates that use the Catalyst context in them.

    As it is not very recommended to access the entire Catalyst context in a model, it should be not recommended to use the context in the templates, because those templates won't be usable in external applications without loading the entire Cat app, but because using the Catalyst context in the templates is very handy, most of us probably prefer to create separate templates for using them in external apps than to provide only sane variables to all the templates.

    Octavian
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20110412/2ed56bda/attachment.htm

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedApr 10, '11 at 1:10p
activeApr 12, '11 at 5:53a
posts11
users5
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2022 Grokbase