Skip to content

Initial Notifications for Subscribed Users#38

Draft
bmckay959 wants to merge 6 commits intoinxilpro:mainfrom
bmckay959:main
Draft

Initial Notifications for Subscribed Users#38
bmckay959 wants to merge 6 commits intoinxilpro:mainfrom
bmckay959:main

Conversation

@bmckay959
Copy link

Initial implementation for sending emails to subscribed users.

@bmckay959 bmckay959 marked this pull request as draft October 1, 2024 23:59
Copy link
Collaborator

@skylerkatz skylerkatz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this will get us what we want, which is that if someone sends 10 updates in a short period of time, we don't want to send 10 emails, we only want to send 1 email.

I might be mistaken by what @DanielCoulbourne originally meant in Discord though.

@bmckay959
Copy link
Author

@skylerkatz Since the notification job uses ShouldBeUnique it will only dispatch a single notification for the delayed dispatch period. I think there is an argument to be made to increase the interval maybe closer to even 10 minutes. The test validates that only 1 notification job is sent in succession, unless I'm not testing correctly on the unique job.

@skylerkatz
Copy link
Collaborator

@skylerkatz Since the notification job uses ShouldBeUnique it will only dispatch a single notification for the delayed dispatch period. I think there is an argument to be made to increase the interval maybe closer to even 10 minutes. The test validates that only 1 notification job is sent in succession, unless I'm not testing correctly on the unique job.

I might be totally reading the docs incorrectly, but I think it will just put the job back on the queue to try again. It will only allow one job of the same lock to process at a time, but it won't drop the job.

@bmckay959
Copy link
Author

@skylerkatz Since the notification job uses ShouldBeUnique it will only dispatch a single notification for the delayed dispatch period. I think there is an argument to be made to increase the interval maybe closer to even 10 minutes. The test validates that only 1 notification job is sent in succession, unless I'm not testing correctly on the unique job.

I might be totally reading the docs incorrectly, but I think it will just put the job back on the queue to try again. It will only allow one job of the same lock to process at a time, but it won't drop the job.

2 different issues being solved here:

  1. UniqueJob middleware
  2. Atomic lock wrapping just to solve any weird edge case where a job would have been dispatched after the job started but not finished

@bmckay959
Copy link
Author

You can now run php artisan migrate:fresh --seed and then manually trigger the check in and see the result.

foreach($check_ins as $check_in) {
$check_in->update(['notifications_sent_at' => now()]);
Cache::lock('send-notifications:'.$this->phone_number->id, 30)->get(function () {
$check_ins = $this->phone_number->not_notified_check_ins()->get();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we want to send all of the check-ins over email since there's no upper limit. We may just want to let the subscriber know their person has checked in and provide a link to the phone number's show page.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, seems sensible to maybe show the latest checkin and link to where the rest are shown.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think we should just add a link directly to their phone number.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I was thinking that since it can only send from the last 2 minutes, we would be at 120 records if someone sent 1 per second(Which seems unrealistic).

If no one is opposed, I'll put the last 10 that have not been notified, then also put a link to the phone number page too.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just made a new commit here. I'm still uncertain about the "no upper limit" and think this should not be solved here, but on a rate limit for the incoming messages in general. I'm allowing up to 1 per second here per phone number in theory. But, the issue is that we can get someone to spam the system and get 100 per second. I'll take a look at this in a different PR.

@hans-lts
Copy link
Contributor

hans-lts commented Oct 2, 2024

I might be totally reading the docs incorrectly, but I think it will just put the job back on the queue to try again. It will only allow one job of the same lock to process at a time, but it won't drop the job.

@skylerkatz might be the WithoutOverlapping middleware you're thinking of?

@skylerkatz
Copy link
Collaborator

I might be totally reading the docs incorrectly, but I think it will just put the job back on the queue to try again. It will only allow one job of the same lock to process at a time, but it won't drop the job.

@skylerkatz might be the WithoutOverlapping middleware you're thinking of?

I just reread the docs, and since it is delayed two min, it does look like no other jobs will be put on the queue (for the phone number) until after the job has run.

$check_ins = $this->phone_number->not_notified_check_ins()->get();

if ($check_ins->count()) {
$this->phone_number->subscriptions()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we fire a SubscriptionWasNotified event and do the rest of the code from this job in the event?

The Check In models themselves are created from events, so if we replay events in the future the notification_sent_at date is going to be null

@inxilpro
Copy link
Owner

inxilpro commented Oct 2, 2024

I haven't had a chance to look this through fully yet, but I think the existence of a notifications_sent_at model field means that there is a better way to handle some logic in here. That's one of the big upsides of event sourcing. We can probably track when notifications are sent on a phone number state, for example. I'll try to look this through later today.

@bmckay959
Copy link
Author

@inxilpro I'm good with whatever here, but my thought process was that we could have multiple messages inside of a single notification. So this would allow us to send a notification for all "check_ins" where notifications_sent_at is null.

If we only use a 2 minutes delay and we say "get everything in the last 2 minutes", we are not guaranteed that it runs exactly at the 2 minute mark, so grabbing all that are null guarantees that we send each check_in.

Also....I've never used Verbs, but wanted to help so may have a fundamental misunderstanding of how it actually works(Though I did see the wizardry at laracon).

Let me know if you want me to do anything specific , but also happy to have you nuke it if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants