Use Noticed for notifications on GPX imports#6939
Use Noticed for notifications on GPX imports#6939pablobm wants to merge 2 commits intoopenstreetmap:masterfrom
Conversation
My initial reaction is that this is the classic ActiveJob model reference problem. Because the job stores a reference to the object, and then looks up the object attributes at some later time, it's not guaranteed that the object still exists when the job runs. This is that same problem on maximum scale, since it affects 100% of the jobs, instead of just a small enough percentage that everyone sweeps the problem under the carpet. My usual approach for similar circumstances is to serialise the required attributes into the job. This means the job runs without needing to load the object. So something like: - GpxImportFailureNotifier.with(:record => trace, :error => e.to_s).deliver_later
+ GpxImportFailureNotifier.with(:error => e.to_s, :trace_name => trace.name, :trace_description => trace.description, :trace_tags => ...etc...).deliver_laterHowever, I don't know if noticed is particularly happy without having a record to associate with. https://github.com/excid3/noticed?tab=readme-ov-file#handling-deleted-records only covers the case where you want to avoid sending notifications for deleted objects, but that's the opposite of what we want here. This also makes me think about how we would handle this with on-site notifications. What if I upload 10 traces and come back to the website next weekend? How will the system know what to write in the site notifications? |
|
Maybe we should just stop deleting the records? We can set If you really wanted you can have a cleanup job as part of the daily cleanup task I mentioned that removed any that were no longer referenced by a notification, once we have the notification cleanup we discussed before. |
| # frozen_string_literal: true | ||
|
|
||
| class GpxImportSuccessNotifier < ApplicationNotifier | ||
| recipients -> { record.user } |
There was a problem hiding this comment.
This is controlling what user the notification is linked to, but it doesn't actually effect where the email goes because the gpx_success mailer determines the recipient itself. Is that going to be confusing?
There was a problem hiding this comment.
Uh, you are right. The logic in the mailer should change to use recipient. Done now.
|
|
||
| trace.stub(:import, gpx) do | ||
| TraceImporterJob.perform_now(trace) | ||
| perform_enqueued_jobs do |
There was a problem hiding this comment.
This needed because the perform_now only runs the trace import job and we need to then run the event job before the mail is submitted now?
There was a problem hiding this comment.
Correct. For completeness:
- The notification jobs launched by
TraceImporterJobare now async (this PR moves them fromdelivertodeliver_later). - The notification jobs in turn launch mailer jobs that are also async.
So the queue needs to be exhausted of the immediate jobs and those generated in turn.
fa9fbc0 to
9f62bea
Compare
|
(EDIT 2026-04-07: comment superseded by my next one). Good points, I should have stopped to think a bit more. I had a look this morning, I see a couple of solutions:
Any preferences? I have rewritten the PR description to reflect the latest changes, as well as answered the questions on specific changes. |
a944d11 to
6aeb440
Compare
580fc1b to
53b5b25
Compare
|
I had another look. There's a third way to do this which I now prefer. The following list supersedes the one above:
In common to all options, any additional arguments are stored in the
Of the options above, this PR now implements option 1. I have also integrated this notification into my proof of concept at master...pablobm:notifications. This is currently deployed to my Dev Server setup, where it can be seen in action in the dashboard of user
|
67bd8b6 to
6ffac5e
Compare
The mailer method now needs to receive the recipient directly, instead of extracting it from the trace record.
The previous code relied on `#deliver` (alias for `#deliver_now`) to immediately deliver the email so that the trace could be deleted. To work around this, we pass the details of the trace instead of the trace record, which won't be available by the time the notifications are ultimately delivered. This means the trace is not there to be the `record`, so we are not passing one. Since we can't get the recipient from the non-existing record, we give the recipient explicitly to `#deliver_later`. Additionally, the mailer method now needs to receive the recipient directly, instead of extracting it from the trace record.
6ffac5e to
d6e9739
Compare

Following #6837, and sibling to #6933, this converts some more code to use Noticed instead of using mailers directly.
The success notification was the simpler of the two. I only needed to adapt the mailer to use the recipient explicitly given in the params, as opposed to extracting it from the trace. This was raised by @tomhughes during review.
The failure notification is a bit more involved. First the two easy changes:
More importantly, there's the issue that the current code deletes the trace immediately after delivering the email synchronously. To work around this, the notifier will not receive a
record, only the metadata as explicit arguments, and the recipient will be given explicitly in thedeliver_latercall.In any case, and as mentioned by @gravitystorm, this raises the question of what to do when we implement on-site notifications and these refer to deleted records. This might involve creating a new model
OnsiteNotificationthat doesn't require other records, instead of piggybacking on the existingNoticed::Notifications.