Scheduling and rescheduling emails - logic

Background
A workflow I have allows users to book meetings. The time/day of the meeting is stored in a table along with other details like the email address.
I send them an email reminder 30 minutes in advance.
Problem
In order to send them an email, a recurring event is set up once a week to go through the table and schedule the email to be sent on time - 30 minutes.
I've added the ability to reschedule the meeting. The problem that creates is that the emails are already scheduled, so users get the reminders at the original time, which is confusing.
What I want to do
I want to be able to send them the email at the rescheduled time, but there are technical limitations to the platform I use, which are:
I cannot set up cron/recurring more frequently than every day. This would probably be better than every week, but if someone rescheduled within the day, they would still get the wrong email.
I cannot remove scheduled events - so any recurring events-based workflow would still send the original email.
I know - this is pretty limiting, but am I even approaching this in the right way?

given your constraints, I'd probably go with 'resign'.
But in all seriousness, if you can't remove scheduled events (and I'm guessing you can't 'move' them because this is too advanced for your CTO to get their head around) then the only way I see it is to break the email send process into two steps - send scheduled event to PROXY in-front of your email sender, check if there is another event (i.e. can you add some 'cancelled/moved to data to the original one) and if so don't send it.

Related

Initial survey won't trigger a series of automated surveys. Can someone advice?

I have a survey called 'Set up and kill switch' (image 1) that will trigger a series of weekly surveys to be sent out, but it's not working. I'm not sure if I didn't set it up correctly or if the logic is not right. I attempted to set it up as sending surveys out via email. In step 3 (refer to image 2), I also specified the conditions: when the set up and kill switch survey has been completed and if the predetermined date in the survey matches the date 'today', the system should activate automated surveys for the next 8 weeks so participants should be receiving them on a weekly basis. However, when I tested this out, I did not receive a survey after completing the kill switch survey. Does anyone have experience in making something like this on redcap? I suspect that the logic is fine, but it could be an issue between linking participant IDs so they aren't receiving anything?
Logic code:
datediff([weekly_questionnai_arm_3i][weekly_date],"today","d","mdy",true)>=0 and ([weekly_questionnai_arm_3i][weekly_killswitch(0)])<>"1"
Kill switch screenshot
Automated survey logic
You need to check the box next to 'Ensure logic is still true before sending invitation?'.
As soon the send logic is true the automated emails will be queued/scheduled for sending - changing the form fields so that the send logic is no longer true will not stop the scheduled emails from being sent unless the 'Ensure logic is still true ...' box is checked.
I also recommend clicking and reading the link underneath "How to use 'stop logic' to disable an automated invite".

Laravel Schedule One-Off Events

Users are able to set up a marketing email send time within my app for random dates as they need them. It is crucial that the emails start to go out exactly when they are scheduled. So, the app needs to create something that fires one time for a specific group of emails at a specific date and time down to the minute. There will be many more dates for other sends in the future, but they are all distinct (so need something other than 'run every xxx date')
I could have a Scheduler task that runs every minute that looks at the dates of any pending tasks in the database and moves to the command that sends those that need sending. But I'm running a multi-tenanted app -- likely not overlap, but seems like a huge hit to multiple databases every minute for every tenant to search through potentially thousands of records per tenant.
What I need (I think) is a way to programmatically set a schedule for each send date, and then remove it. I liked this answer or perhaps using ->between($startMin, $endMin), without the every xxx instruction, or even using the cron function within Scheduler to set up one single time for each group that needs to be sent. Not sure I'm using this the way it was intended though?
Would this even work? I programmatically created a schedule from within a test method, and it was added to the schedule queue based on the dump of the $schedule I created, showing all schedules - but it did not show up via this method found from this answer:
$schedule = app()->make(\Illuminate\Console\Scheduling\Schedule::class);
$events = collect($schedule->events())->filter(function (\Illuminate\Console\Scheduling\Event $event) {
return stripos($event->command, 'YourCommandHere');
});
It also did not output anything, so I'm wondering if programmatically creating a schedule outside of Kernel.php is not the way to go.
Is there another way? I don't know scheduler well enough to know if these one-off schedules permanently remain somewhere, are they deleted after their intended single use, taking up memory, etc?
Really appreciate any help or guidance.

Fire Message Event Only when These other Messages have been sent

I'm working on architecting a micro-service solution where most code will be C# and most likely Angular for any front end. My question is about message chaining. I am still figuring out what message broker to use; Azure Service Bus , RabbitMQ, etc.. There is a concept which I haven't found much about.
How do I handle cases when I want to fire a message when a specific set of messages have fired. An example but not part of my actual solution: I want to say Notify someone when pays a bill. We send a message "PAIDBILL"
which will fire off microservices which will be processed independently:
FinanceService to Debit the ledger and fire "PaymentPosted"
EmailService: email Customer Saying thank you for paying the bill
"CustomerPaymentEmailSent"
DiscountService: Check if they get a discount for paying on time then send
"CustomerCanGetPaymentDiscount"
If all three messages have fired for the Same PAIDBILL: Message "PaymentPosted", "CustomerPaymentEmailSent", "CustomerCanGetPaymentDiscount"
then I want to email the customer that they will get a discount on their next bill. It Must be done AFTER all three have tiggered and the order doesn't matter. How do I Schedule a new message to be sent "EmailNextTimeDiscount" message, without having to poll for what messages have fired every minute, hour, day?
All I can think of is to have a SQL table which marks that each one is complete (by locking the table) and when the last one is filled then send off the message. Would this be a good solution? I find it an anti-pattern for the micro-service & message queue design.
If you're using messages (e.g. Service Bus / RabbitMQ), then I think the solution you have described is the best one. This type of design - where services have knowledge about the other domains in the system - is typically known as choreography.
You'll want to pick a service which will be responsible for this business logic. That service will need to receive all the preceding types of messages so that it can determine when (if) all have been met, which it probably wants to do by recording which of the gates have already passed in a database.
One alternative you could consider is chaining the business processes instead of doing them in parallel. So...
PAYBILL causes FinanceService to Debit the ledger and fire "PaymentPosted"
"PayentPosted" causes EmailService to email Customer Saying thank you for paying the bill and broadcasts "CustomerPaymentEmailSent"
"CustomerPaymentEmailSent" causes DicsountService to check if they get a discount for paying on Time then sends "CustomerCanGetPaymentDiscount"
The email you want to send is just triggered by "CustomerCanGetPaymentDiscount".
If I'm honest, I would switch around the dependency model you're using at this last stage. So, instead of some component listening for "CustomerCanGetPaymentDiscount" events from DiscountService and sending an email, I think I would instead have the DiscountService tell some other component to send an email. It seems natural to me for something that calculates discounts to know that an email should be sent. It seems less natural for something that sends emails to know about discounts (and everything else that needs emails sent). This is why I don't like architectures where the assumption is that every message should be an event and every action should be triggered by an event: it removes a lot of decisions about where domain logic can live, because the message receiver always has to know about the domain of the message sender, never vice versa.

Laravel - Send Mail in Future based on condition

I want to send emails to various users based on the schedules they have set.
I read about beanstalkd, queues and Delayed Message Queueing and for now it looks like fitting in:
$when = Carbon::now()->addMinutes($minutes); // i can calculate minutes at this moment
\Mail::to($user)->later($when, new \App\Mail\TestMail);
But i'm not quite sure on few things:
User can cancel a future schedule. In that case how do i cancel an email that's suppose to send in future. Can i set condition somewhere that gets checked before sending the actual email? Tried return false on handle method of \App\Mail\TestMail and it started throwing error
Am i using the right approach. I also read about Scheduler but i don't get how i am going to cancel future emails(if they need to be)
There are many ways to approach this. Personally I would queue the emails on a schedule rather than adding them to the queue for later.
So you run a scheduled task once a day (or hour, or minute) which runs a query to select which users require an email, then using that result set, you add a job to the queue for each result.
This way, if a user unsubscribes, you don't have to worry about removing already queued jobs.
Laravel offers quite a nice interface for creating scheduled jobs (https://laravel.com/docs/5.4/scheduling) which can then be called via a cronjob.

Can I send multiple ShellToast notifications at once?

What happens, if I send multiple ShellToast notifications from background agent at once, for example in ToDo list app I want to notify that 3 tasks should be finished today?
Is it allowed or recommended? Would the user see all three toasts or only the first one?
The scheduled agent only runs once and it's up to you to manage which toast will be shown. In those scenarios you should be using a counter...possibly.
The way I've worked around this sort of thing in the past is just track a time or which toasts have been shown in sort of a queue and just show one every update so you could just rotate through your queue throughout the day until the tasks in app are no longer valid. Or, based on the phone's time, determine what to show (they fire every 30 min or so).
Ultimately, the optimal way is probably having one toast that says "You have 3 tasks to complete" etc etc.
Hope one of those solutions might help!
// Jed

Resources