Skip to content

Commit

Permalink
Create jobs to trigger sending all alias as create events (#2126)
Browse files Browse the repository at this point in the history
* Create jobs to trigger sending all alias as create events

* Set events in past tense

* fix test

* Removed debug log

* Log messages
  • Loading branch information
acasajus authored Jun 7, 2024
1 parent b931518 commit 8a77a8b
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 57 deletions.
9 changes: 7 additions & 2 deletions app/alias_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@
)
from app.errors import AliasInTrashError
from app.events.event_dispatcher import EventDispatcher
from app.events.generated.event_pb2 import AliasDeleted, AliasStatusChange, EventContent
from app.events.generated.event_pb2 import (
AliasDeleted,
AliasStatusChanged,
EventContent,
)
from app.log import LOG
from app.models import (
Alias,
Expand Down Expand Up @@ -468,9 +472,10 @@ def transfer_alias(alias, new_user, new_mailboxes: [Mailbox]):


def change_alias_status(alias: Alias, enabled: bool, commit: bool = False):
LOG.i(f"Changing alias {alias} enabled to {enabled}")
alias.enabled = enabled

event = AliasStatusChange(
event = AliasStatusChanged(
alias_id=alias.id, alias_email=alias.email, enabled=enabled
)
EventDispatcher.send_event(alias.user, EventContent(alias_status_change=event))
Expand Down
2 changes: 2 additions & 0 deletions app/api/views/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
ErrAddressInvalid,
)
from app.extensions import limiter
from app.log import LOG
from app.models import Alias, Contact, Mailbox, AliasMailbox


Expand Down Expand Up @@ -185,6 +186,7 @@ def toggle_alias(alias_id):
return jsonify(error="Forbidden"), 403

alias_utils.change_alias_status(alias, enabled=not alias.enabled)
LOG.i(f"User {user} changed alias {alias} enabled status to {alias.enabled}")
Session.commit()

return jsonify(enabled=alias.enabled), 200
Expand Down
1 change: 1 addition & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ def sl_getenv(env_var: str, default_factory: Callable = None):
JOB_DELETE_DOMAIN = "delete-domain"
JOB_SEND_USER_REPORT = "send-user-report"
JOB_SEND_PROTON_WELCOME_1 = "proton-welcome-1"
JOB_SEND_ALIAS_CREATION_EVENTS = "send-alias-creation-events"

# for pagination
PAGE_LIMIT = 20
Expand Down
46 changes: 28 additions & 18 deletions app/events/generated/event_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions app/events/generated/event_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Map

DESCRIPTOR: _descriptor.FileDescriptor

class UserPlanChange(_message.Message):
class UserPlanChanged(_message.Message):
__slots__ = ("plan_end_time",)
PLAN_END_TIME_FIELD_NUMBER: _ClassVar[int]
plan_end_time: int
Expand All @@ -27,7 +27,7 @@ class AliasCreated(_message.Message):
enabled: bool
def __init__(self, alias_id: _Optional[int] = ..., alias_email: _Optional[str] = ..., alias_note: _Optional[str] = ..., enabled: bool = ...) -> None: ...

class AliasStatusChange(_message.Message):
class AliasStatusChanged(_message.Message):
__slots__ = ("alias_id", "alias_email", "enabled")
ALIAS_ID_FIELD_NUMBER: _ClassVar[int]
ALIAS_EMAIL_FIELD_NUMBER: _ClassVar[int]
Expand All @@ -45,11 +45,11 @@ class AliasDeleted(_message.Message):
alias_email: str
def __init__(self, alias_id: _Optional[int] = ..., alias_email: _Optional[str] = ...) -> None: ...

class AliasCreateList(_message.Message):
__slots__ = ("event",)
EVENT_FIELD_NUMBER: _ClassVar[int]
event: _containers.RepeatedCompositeFieldContainer[AliasCreated]
def __init__(self, event: _Optional[_Iterable[_Union[AliasCreated, _Mapping]]] = ...) -> None: ...
class AliasCreatedList(_message.Message):
__slots__ = ("events",)
EVENTS_FIELD_NUMBER: _ClassVar[int]
events: _containers.RepeatedCompositeFieldContainer[AliasCreated]
def __init__(self, events: _Optional[_Iterable[_Union[AliasCreated, _Mapping]]] = ...) -> None: ...

class EventContent(_message.Message):
__slots__ = ("user_plan_change", "user_deleted", "alias_created", "alias_status_change", "alias_deleted", "alias_create_list")
Expand All @@ -59,13 +59,13 @@ class EventContent(_message.Message):
ALIAS_STATUS_CHANGE_FIELD_NUMBER: _ClassVar[int]
ALIAS_DELETED_FIELD_NUMBER: _ClassVar[int]
ALIAS_CREATE_LIST_FIELD_NUMBER: _ClassVar[int]
user_plan_change: UserPlanChange
user_plan_change: UserPlanChanged
user_deleted: UserDeleted
alias_created: AliasCreated
alias_status_change: AliasStatusChange
alias_status_change: AliasStatusChanged
alias_deleted: AliasDeleted
alias_create_list: AliasCreateList
def __init__(self, user_plan_change: _Optional[_Union[UserPlanChange, _Mapping]] = ..., user_deleted: _Optional[_Union[UserDeleted, _Mapping]] = ..., alias_created: _Optional[_Union[AliasCreated, _Mapping]] = ..., alias_status_change: _Optional[_Union[AliasStatusChange, _Mapping]] = ..., alias_deleted: _Optional[_Union[AliasDeleted, _Mapping]] = ..., alias_create_list: _Optional[_Union[AliasCreateList, _Mapping]] = ...) -> None: ...
alias_create_list: AliasCreatedList
def __init__(self, user_plan_change: _Optional[_Union[UserPlanChanged, _Mapping]] = ..., user_deleted: _Optional[_Union[UserDeleted, _Mapping]] = ..., alias_created: _Optional[_Union[AliasCreated, _Mapping]] = ..., alias_status_change: _Optional[_Union[AliasStatusChanged, _Mapping]] = ..., alias_deleted: _Optional[_Union[AliasDeleted, _Mapping]] = ..., alias_create_list: _Optional[_Union[AliasCreatedList, _Mapping]] = ...) -> None: ...

class Event(_message.Message):
__slots__ = ("user_id", "external_user_id", "partner_id", "content")
Expand Down
1 change: 1 addition & 0 deletions app/handler/unsubscribe_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def _disable_alias(
mailbox.email, alias
):
return status.E509
LOG.i(f"User disabled alias {alias} via unsubscribe header")
alias_utils.change_alias_status(alias, enabled=False)
Session.commit()
enable_alias_url = config.URL + f"/dashboard/?highlight_alias_id={alias.id}"
Expand Down
40 changes: 40 additions & 0 deletions app/jobs/event_jobs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from app.events.event_dispatcher import EventDispatcher, Dispatcher
from app.events.generated.event_pb2 import EventContent, AliasCreated, AliasCreatedList
from app.log import LOG
from app.models import User, Alias


def send_alias_creation_events_for_user(
user: User, dispatcher: Dispatcher, chunk_size=50
):
if user.disabled:
LOG.i("User {user} is disabled. Skipping sending events for that user")
return
chunk_size = min(chunk_size, 50)
event_list = []
for alias in (
Alias.yield_per_query(chunk_size)
.filter_by(user_id=user.id)
.order_by(Alias.id.asc())
):
event_list.append(
AliasCreated(
alias_id=alias.id,
alias_email=alias.email,
alias_note=alias.note,
enabled=alias.enabled,
)
)
if len(event_list) >= chunk_size:
EventDispatcher.send_event(
user,
EventContent(alias_create_list=AliasCreatedList(events=event_list)),
dispatcher=dispatcher,
)
event_list = []
if len(event_list) > 0:
EventDispatcher.send_event(
user,
EventContent(alias_create_list=AliasCreatedList(events=event_list)),
dispatcher=dispatcher,
)
4 changes: 2 additions & 2 deletions app/subscription_webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from app import config
from app.events.event_dispatcher import EventDispatcher
from app.events.generated.event_pb2 import EventContent, UserPlanChange
from app.events.generated.event_pb2 import EventContent, UserPlanChanged
from app.log import LOG
from app.models import User

Expand Down Expand Up @@ -34,5 +34,5 @@ def execute_subscription_webhook(user: User):
except RequestException as e:
LOG.error(f"Subscription request exception: {e}")

event = UserPlanChange(plan_end_time=sl_subscription_end)
event = UserPlanChanged(plan_end_time=sl_subscription_end)
EventDispatcher.send_event(user, EventContent(user_plan_change=event))
9 changes: 8 additions & 1 deletion job_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
render,
)
from app.import_utils import handle_batch_import
from app.jobs.event_jobs import send_alias_creation_events_for_user
from app.jobs.export_user_data_job import ExportUserDataJob
from app.log import LOG
from app.models import User, Job, BatchImport, Mailbox, CustomDomain, JobState
Expand Down Expand Up @@ -264,8 +265,14 @@ def process_job(job: Job):
user_id = job.payload.get("user_id")
user = User.get(user_id)
if user and user.activated:
LOG.d("send proton welcome email to user %s", user)
LOG.d("Send proton welcome email to user %s", user)
welcome_proton(user)
elif job.name == config.JOB_SEND_ALIAS_CREATION_EVENTS:
user_id = job.payload.get("user_id")
user = User.get(user_id)
if user and user.activated:
LOG.d(f"Sending alias creation events for {user}")
send_alias_creation_events_for_user(user)
else:
LOG.e("Unknown job name %s", job.name)

Expand Down
28 changes: 13 additions & 15 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions proto/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ syntax = "proto3";

package simplelogin_events;

message UserPlanChange {
message UserPlanChanged {
uint32 plan_end_time = 1;
}

Expand All @@ -16,7 +16,7 @@ message AliasCreated {
bool enabled = 4;
}

message AliasStatusChange {
message AliasStatusChanged {
uint32 alias_id = 1;
string alias_email = 2;
bool enabled = 3;
Expand All @@ -27,18 +27,18 @@ message AliasDeleted {
string alias_email = 2;
}

message AliasCreateList {
repeated AliasCreated event = 1;
message AliasCreatedList {
repeated AliasCreated events = 1;
}

message EventContent {
oneof content {
UserPlanChange user_plan_change = 1;
UserPlanChanged user_plan_change = 1;
UserDeleted user_deleted = 2;
AliasCreated alias_created = 3;
AliasStatusChange alias_status_change = 4;
AliasStatusChanged alias_status_change = 4;
AliasDeleted alias_deleted = 5;
AliasCreateList alias_create_list = 6;
AliasCreatedList alias_create_list = 6;
}
}

Expand Down
Loading

0 comments on commit 8a77a8b

Please sign in to comment.