Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Email event cluster's subscribed users when an event is created #3362

Closed
wants to merge 23 commits into from

Conversation

schradert
Copy link
Contributor

Here is an incomplete attempt at sending emails as a background job when an event is created. An email would be sent to any user that is subscribed to the cluster the event was created in. I include some filters to prevent spamming, such as excluding events in the four largest clusters, only allowing events created by users with completed profiles to send emails, and excluding subscribers too far away when the number notified would exceed the maximum.

Currently, the background job test is failing when during the first event/cluster query in the job handler can't find a matching event. Even without the association to a cluster in the query, no event matches the payload ID. Could use some help here @ItsiW @aapeliv, I could make a codepairing work too for running through it and debugging. I suspect I'm just calling the event testing functions like create_event and create_community wrong, or in the wrong context. Similar tests are passing. Perhaps I should rewrite the test from basics if these aren't adaptable.

Backend checklist

  • Formatted my code by running autoflake -r -i --remove-all-unused-imports src && isort . && black . in app/backend
  • Added tests for any new code or added a regression test if fixing a bug
  • All tests pass
  • Run the backend locally and it works
  • Added migrations if there are any database changes, rebased onto develop if necessary for linear migration history

Copy link
Member

@aapeliv aapeliv left a comment

Choose a reason for hiding this comment

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

I still worry about misuse of this, we have to be pretty careful. But we do need to get somethign implemented. One option would be to only send out notifications if the organizer is a community builder, that way there is some vetting.

Another thing: are we sure we want to send out the notification when the event is created, or should there just be a button on the event saying "send email" when the organizer has finished setting it up and is ready for the info to go out?

app/backend/src/couchers/jobs/handlers.py Outdated Show resolved Hide resolved
app/backend/src/couchers/jobs/handlers.py Outdated Show resolved Hide resolved
@aapeliv
Copy link
Member

aapeliv commented Dec 11, 2022

@schradert could you rebase this onto develop, please, that way I could look at the failing test and see what's up with the event ids? (sorry, I looked at code before looking at what you wrote :) )

@schradert schradert force-pushed the backend/feature/event-email branch from 2bb0e0e to b84b9a7 Compare May 6, 2023 20:41
@schradert
Copy link
Contributor Author

@schradert could you rebase this onto develop, please, that way I could look at the failing test and see what's up with the event ids? (sorry, I looked at code before looking at what you wrote :) )

Just rebased

@schradert
Copy link
Contributor Author

Another thing: are we sure we want to send out the notification when the event is created, or should there just be a button on the event saying "send email" when the organizer has finished setting it up and is ready for the info to go out?

I like this idea, but it requires frontend work. Should we wait until that is implemented on the frontend? Will the frontend repo be merged into this one so that we can have the PR address this if we prefer that approach with no intermediate solution?

@schradert
Copy link
Contributor Author

I still worry about misuse of this, we have to be pretty careful. But we do need to get something implemented. One option would be to only send out notifications if the organizer is a community builder, that way there is some vetting.

Okay I can work on this right now. I was told that there are many events not made by community builders. Is the idea we want to encourage them to become community builders in order to get this kind of event exposure?

@schradert schradert requested a review from aapeliv May 8, 2023 17:42
Copy link
Member

@aapeliv aapeliv left a comment

Choose a reason for hiding this comment

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

This is looking pretty good. A few things:

  • There really needs to be some way to unsubscribe from these; I suggest you make a simple boolean in the user model. I can probably try hacking this together.

  • I had a look at the DB, here are the biggest communities:

 cluster_id |              name               | count 
------------+---------------------------------+-------
          2 | Global Community                | 29076
         11 | Europe, Africa, and Middle East | 18065
          5 | Americas                        |  8419
         43 | United States of America        |  5873
          8 | Asia-Pacific                    |  2906
        126 | Germany                         |  2422
         46 | Turkey                          |  2100
        570 | United Kingdom                  |  1673
        497 | France                          |  1400
        374 | Italy                           |  1327
         95 | Canada                          |  1225
         49 | Istanbul                        |  1003
        397 | Spain                           |   996
       1019 | Poland                          |   887
        734 | Netherlands                     |   797
         55 | Russia                          |   765
         14 | Australia                       |   670
         17 | New York City area              |   557
        153 | Berlin                          |   548
        180 | Brasil                          |   526
        888 | Belgium                         |   503
        491 | Portugal                        |   465
        500 | Paris                           |   461
        189 | Sweden                          |   397

I would say the best thing would be to send notifications only for events in leaf clusters; but the 1k user limit is OK too if it's too much effort.

  • The email needs to be fleshed out and polished, and we need to double check users can't inject random links into it, etc!

app/backend/src/couchers/models.py Outdated Show resolved Hide resolved
app/docker-compose.yml Outdated Show resolved Hide resolved
app/backend/templates/event_created.md Outdated Show resolved Hide resolved
@aapeliv
Copy link
Member

aapeliv commented Aug 7, 2023

Let me know by tagging here when you're ready for another review!

schradert and others added 19 commits September 17, 2023 13:18
…lready taken by the ControlCe service which autorestarts on this port
…ne handler.

The handler includes some validation to ensure users are not spammed with event emails.
For example, if the event creator has not completed their profile, we abort the event creation.
It's probably a very small edge case that an email will be sent out for a created event.
I also included a filter for the largest nodes, global and regional.
I then grab all the users that are subscribed to a cluster and send an email to all of them for the event.
If there are too many users, I limit the users emailed to those in a 20km radius of the event occurrence.
…t is called when enqueuing the background job\nI make sure to pass in the user and event information to the email
The logic around max_users and max_radius already handles this
situation. We just keep the one for Global right now because that's
what all virtual events are assigned to.
this is more expected because it matches with the container port. i
originally did this because AirPlay runs on 5000 and i thought it made
sense to make the code work more generally for people since many have
macOS with this same issue, but it's probably better to not enforce
local differences like this on the codebase, so i just turn AirPlay off.
this allows accessing them straight from the event object to avoid
repetitive join logic in various places
it could be interesting to replace the timezone of the event
time (defaults currently as UTC) to reflect the user's timezone, but
this became complicated...
Now the logic for selecting subscribers to send emails is the following:

1. If the creator doesn't have a completed profile, abort
2. Go through all clusters associated with the event and only exclude
Global Community
3. If a cluster is a leaf node or the creator is an admin, always consider all cluster subscribers
4. Otherwise, filter out people not in a 20km radius of the event (there
is always a default first occurrence for an event, so we just choose
that as the location)
@schradert
Copy link
Contributor Author

Let me know by tagging here when you're ready for another review!

@ItsiW @aapeliv I think the PR is ready for review now finally. Sorry it took so long! Not sure what's going on with the tests.

@schradert schradert marked this pull request as ready for review September 17, 2023 20:20
@schradert schradert changed the title [WIP] Email event cluster's subscribed users when an event is created Email event cluster's subscribed users when an event is created Sep 17, 2023
this is already defined in the clusters model with a backref. the
redundant definition was creating an issue with starting up the database
because it couldn't create the same relation twice
this follows the instructions at docs/database.md
@schradert
Copy link
Contributor Author

@aapeliv I followed the instructions at docs/database.md to add a migration to the database for the field User.send_event_notifications. It seems the new migration file has a lot more than just that change, and when I try to spin up the docker network, it fails with cannot drop table state_lookup because extension postgis_geocoder requires it. The migration file does clearly include an op.drop_table("state_lookup") but I don't know why that's showing up. I don't know how to clean up the migration file properly. My thought would be to just include the line relevant to your unsubscribe feature and delete everything else but I don't know if that's a good idea.

@schradert
Copy link
Contributor Author

schradert commented Sep 24, 2023

@aapeliv also I'm thinking we probably want the unsubscribe feature to be more granular. I imagine people want to unsubscribe for a more specific reason than wanting to never receive an email for a new event. My thought is it could be just for the event in question. Maybe in the future it could have a cluster-level control too. In this case though, my idea would be to also add this boolean flag you introduced to the EventSubscription and/or ClusterSubscription models.

@aapeliv
Copy link
Member

aapeliv commented Sep 26, 2023

@aapeliv I followed the instructions at docs/database.md to add a migration to the database for the field User.send_event_notifications. It seems the new migration file has a lot more than just that change, and when I try to spin up the docker network, it fails with cannot drop table state_lookup because extension postgis_geocoder requires it. The migration file does clearly include an op.drop_table("state_lookup") but I don't know why that's showing up. I don't know how to clean up the migration file properly. My thought would be to just include the line relevant to your unsubscribe feature and delete everything else but I don't know if that's a good idea.

It seems it picked up some postgis system tables. It has some functionality built in for US geo things, called "tiger" and another one, I think.

Yeah just try deleting all but the stuff you added. There should be a test to pick up differences too.

Copy link
Member

@aapeliv aapeliv left a comment

Choose a reason for hiding this comment

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

Looks very good, just some minor comments.

select(User)
.join(ClusterSubscription, ClusterSubscription.user_id == User.id)
.where(ClusterSubscription.cluster_id == cluster.id)
.where(func.ST_Contains(func.ST_Buffer(event.occurrences[0].geom, max_radius), User.geom))
Copy link
Member

Choose a reason for hiding this comment

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

I think func.ST_DWithin(User.geom, event.occurrences[0].geom, max_radius / 111111) is preferred, according to the web. These geography fields use WGS84 coordinates, so distances are measured in degrees; a degree is ~111km at the equator.

A new event was created in your area!

{% set clusters = event.clusters %}
{% set is_plural = event.clusters | length > 1 %}
Copy link
Member

Choose a reason for hiding this comment

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

Nice templating :D

@aapeliv
Copy link
Member

aapeliv commented Sep 26, 2023

@schradert See if you can fix the tests, if not let me know and I can have a look

aapeliv added a commit that referenced this pull request Apr 11, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request Apr 11, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request Apr 13, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request Apr 14, 2024
Builds on some work from #3362 by @schradert
@aapeliv aapeliv added the backend This issue relates to the python backend label Apr 20, 2024
aapeliv added a commit that referenced this pull request Apr 20, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request Apr 24, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request May 3, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request May 19, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request May 19, 2024
Builds on some work from #3362 by @schradert
aapeliv added a commit that referenced this pull request May 19, 2024
Builds on some work from #3362 by @schradert
@schradert
Copy link
Contributor Author

@aapeliv should we close this now that you've reworked in elsewhere?

@aapeliv
Copy link
Member

aapeliv commented May 23, 2024

@aapeliv should we close this now that you've reworked in elsewhere?

Yes, let's do that!

@aapeliv aapeliv closed this May 23, 2024
@schradert schradert deleted the backend/feature/event-email branch May 23, 2024 22:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend This issue relates to the python backend
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants