3

G'day Is there a way to force the mail spooler to run, rather than wait for the delay period set in CFAdmin?

I had a look through the admin API and could not see anything, so I suspect the answer might be "no", but I thought perhaps someone knows how to call the underlying process?

The reason for wanting to do this is a bit of an edge case. On our testing server we've got the spooler set to run every 15sec, which - for most things - is fine. However we have an increasing number of unit tests (which run on this same test server) which inspect the content of email messages that have been sent for various elements we need to verify the integrity of. Currently the tests check the Undelivr dir and if the relevant mail message is not found, waits 2sec and tries again, waiting for a total of 20sec before deciding the test needs to be aborted (20sec is an arbitrary amount; 15sec between spool intervals, and some "wriggle room"). This works fine, but it means the unit test suite ends up running slower than it really needs to be, because these email-checking tests have this "up to 20sec" pause in them.

It's not the end of the world, but it's something I'd like to deal with if poss.

I guess one approach I could take is to check the spool dir instead, but I'd rather wait until the email message is "parked" in the Undelivr dir if poss. I'm slightly hesitant to mess with stuff in the spool dir (for no informed reason, granted).

Anyway, all my waffle aside, the short version of the question is "is there any way to force mail spool to run via code?".

Cheers.

Adam Cameron
  • 29,677
  • 4
  • 37
  • 78

3 Answers3

1
<cfobject action="CREATE"
   type="JAVA"
   class="coldfusion.server.ServiceFactory"
   name="factory">

<cfset MailSpoolService = factory.getMailSpoolService()> 
<cfset MailSpoolService.restart()>
Shawn Holmes
  • 3,752
  • 22
  • 25
  • Not entirely clear why I was downvoted, but this *is* a programmatic way to kick off the ColdFusion spooler--unless someone has a rebuttal? – Shawn Holmes Oct 10 '11 at 15:14
  • Just a note: it wasn't me who downvoted you, Shawn; and it looks a reasonable answer to me. I'll check it out a bit later. The only thing I can think is that perhaps whoever complained didn't like the fact you were restarting the whole service? Dunno. It's a bit impolite & unhelpful that they didn't explain themselves. – Adam Cameron Oct 10 '11 at 15:48
  • Would it really need to be restarted? I see a run() in there but can't say I have really messed with the Mail Spool Service before. – Snipe656 Oct 10 '11 at 19:41
  • Shawn, I have now tested this. Have you ever run this code and known for it to "work" (ie: for it to fulfil the requirement of my question), or are you just offering untested speculative code?I ask because for me it does not work. It still takes the same amount of time for the mail message to be spooled. – Adam Cameron Oct 11 '11 at 08:17
  • @Snipe656: the run() method starts an entirely new mail spool task. So whilst it will seem to be doing what I want, I'd end up with multiple tasks all hovering over the mail directory, ALL trying to process the mail. And, of course, calling run() too many times would eventually ceate too many tasks for the server to cope with, and flatten it :-( – Adam Cameron Oct 11 '11 at 09:22
  • Was there also a stop() in there? Guess no way to just stop a process that you have started? – Snipe656 Oct 11 '11 at 15:09
  • It may very well be that you've hit your threshold for max time to process the directory, and no amount of programmatic increase in mail spool request frequency will out-do the amount of time necessary to process the dir, looking for the spooled mail and process it. Have you tried setting the mail spool to be in memory only? – Shawn Holmes Oct 11 '11 at 21:40
  • Sorry Shawn, that's not what I asked. What I asked was whether the code you offered as a solution had been tested and proven to be a solution, or whether it was just based on speculation. Can you clarify? Cheers. – Adam Cameron Oct 11 '11 at 22:49
  • I have not tested it--it is based on this answer: http://stackoverflow.com/questions/94932/coldfusion-mail-queue-stops-processing – Shawn Holmes Oct 12 '11 at 20:15
1

OK, I've got the official line from one of the Adobe engineers on this: basically what I'm trying to do can't be done, as it currently stands.

There's a method to re-run the email spool, but it's private to the mail spool service.

Oh well.

Cheers to everyone who looked into this for me & offered suggestions.

Adam Cameron
  • 29,677
  • 4
  • 37
  • 78
  • You can invoke a private method. Just change its accessibility to true: `method.setAccessible(true)`. Whether or not you should do it is a different story. – Leigh Oct 14 '11 at 12:13
  • Cheers Leigh: I'll look into that. It's just for a unit test so I'm OK with being a bit "naughty". – Adam Cameron Oct 14 '11 at 13:29
  • Okay, cool. I do not know which method(s) are the right ones. But calling `refreshSpoolFiles` followed by `deliverStandard` *seemed* to do the trick for me. I will post my sample code in case it helps. – Leigh Oct 14 '11 at 13:37
0

There's a method to re-run the email spool, but it's private to the mail spool service.

As I mentioned in the comments, you can invoke a private method by setting its accessibility to true. Not something you want to do "willy-nilly", but probably okay for a unit test.

Disclaimer: I would not swear these are the right methods. But it did seem to kick-off mail processing in my brief tests.

<cfscript>
    // Tested with CF 9.0.1
    factory = createObject("java", "coldfusion.server.ServiceFactory");
    spoolService = factory.getMailSpoolService();
    spoolClass = spoolService.getClass();

    methodToCall = spoolClass.getDeclaredMethod("refreshSpoolFiles", []);
    methodToCall.setAccessible(true);
    methodToCall.invoke(spoolService,  []);

    methodToCall = spoolClass.getDeclaredMethod("deliverStandard", []);
    methodToCall.setAccessible(true);
    methodToCall.invoke(spoolService,  []);
</cfscript>
Leigh
  • 28,765
  • 10
  • 55
  • 103