Commit Graph

333 Commits

Author SHA1 Message Date
Anders Kaseorg fd0ab7c4ec tornado: Call close() on Django HttpResponse objects.
This is necessary to break the uncollectable reference cycle created
by our ‘request_notes.saved_response = json_response(…)’, Django’s
‘response._resource_closers.append(request.close)’, and Python’s
https://bugs.python.org/issue44680.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-20 11:07:36 -07:00
Anders Kaseorg 6564b258f1 request: Weaken ZulipRequestNotes.tornado_handler reference.
This prevents a memory leak arising from Python’s inability to collect
a reference cycle from a WeakKeyDictionary value to its key
(https://bugs.python.org/issue44680).

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-19 16:48:23 -07:00
Anders Kaseorg 7c32134fb5 Revert "Revert "request: Refactor to record rate limit data using ZulipRequestNotes.""
This reverts commit 49eab4efef.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-19 16:48:23 -07:00
Anders Kaseorg fb3ddf50d4 python: Fix mypy no_implicit_reexport errors.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-16 14:02:31 -07:00
PIG208 49eab4efef Revert "request: Refactor to record rate limit data using ZulipRequestNotes."
This reverts commit 3f9a5e1e17.
2021-07-16 09:01:20 -07:00
PIG208 c03b9c95ad request: Store client information using ZulipRequestNotes.
This concludes the HttpRequest migration to eliminate arbitrary
attributes (except private ones that are belong to django) attached
to the request object during runtime and migrated them to a
separate data structure dedicated for the purpose of adding
information (so called notes) to a HttpRequest.
2021-07-14 12:01:07 -07:00
PIG208 5167a93229 request: Move tornado_handler to ZulipRequestNotes. 2021-07-14 12:01:07 -07:00
PIG208 742c17399e request: Move miscellaneous attributes to ZulipRequestNotes.
This includes the migration of fields that require trivial changes
to be migrated to be stored with ZulipRequestNotes.

Specifically _requestor_for_logs, _set_language, _query, error_format,
placeholder_open_graph_description, saveed_response, which were all
previously set on the HttpRequest object at some point. This migration
allows them to be typed.
2021-07-14 12:01:07 -07:00
PIG208 5475334b16 request: Refactor to store requestor_for_logs in ZulipRequestNotes. 2021-07-14 12:01:07 -07:00
PIG208 3f9a5e1e17 request: Refactor to record rate limit data using ZulipRequestNotes.
We will no longer use the HttpRequest to store the rate limit data.
Using ZulipRequestNotes, we can access rate_limit and ratelimits_applied
with type hints support. We also save the process of initializing
ratelimits_applied by giving it a default value.
2021-07-14 12:01:07 -07:00
PIG208 da6e5ddcae request: Move log_data from HttpRequest to ZulipRequestNotes. 2021-07-14 12:01:05 -07:00
PIG208 03693cd27e request: Map HttpRequest to ZulipRequestNotes for typing.
We create a class called ZulipRequestNotes as a new home to all the
additional attributes that we add to the Django HttpRequest object.
This allows mypy to do the typecheck and also enforces type safety.

Most of the attributes are added in the middleware, and thus it is
generally safe to assert that they are not None in a code path that
goes through the middleware. The caller is obligated to do manual
the type check otherwise.

This also resolves some cyclic dependencies that zerver.lib.request
have with zerver.lib.rate_limiter and zerver.tornado.handlers.
2021-07-14 11:52:42 -07:00
Abhijeet Prasad Bodas bf15c0235a notifications: Remove unused fields in queue events.
* `stream_name`: This field is actually redundant. The email/push
  notifications handlers don't use that field from the dict, and they
  anyways query for the message, so we're safe in deleting this field,
  even if in the future we end up needing the stream name.

* `timestamp`: This is totally unused by the email/push notification
  handlers, and aren't sent to push clients either.

* `type` is used only for the push notifications handler, since only
  push notifications can be revoked, so we move them to only run there.
2021-07-08 11:22:45 -07:00
Anders Kaseorg 4a04cda956 tornado: Remove unused logger variable.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-07 15:13:40 -07:00
Abhijeet Prasad Bodas 167be7dbdc mentions: Send user group mention data to notification notices.
We will later use this data to include text like:
`<sender> mentioned @<user_group>` instead of the current
`<sender> mentioned you` when someone mentions a user group
the current user is a part of in email/push notification.

Part of #13080.
2021-07-05 14:23:59 -07:00
Tim Abbott 64aa8f80a0 events: Add heartbeat events to tests and documentation.
Heartbeat events are an important part of the API, even though they
are noops, so it's important to document them.
2021-07-01 17:14:32 -07:00
PIG208 dcbb2a78ca python: Migrate most json_error => JsonableError.
JsonableError has two major benefits over json_error:
* It can be raised from anywhere in the codebase, rather than
  being a return value, which is much more convenient for refactoring,
  as one doesn't potentially need to change error handling style when
  extracting a bit of view code to a function.
* It is guaranteed to contain the `code` property, which is helpful
  for API consistency.

Various stragglers are not updated because JsonableError requires
subclassing in order to specify custom data or HTTP status codes.
2021-06-30 16:22:38 -07:00
Abhijeet Prasad Bodas e196ea7e64 event_queue: Consistently user `user_notifications_data` as variable name.
This disambiguates this object from the those sent via the `send_event`
calls, which are also called "user_data".
2021-06-25 08:54:01 -07:00
Abhijeet Prasad Bodas 733e0ae75e notification_data: Rename `sender_id` -> `acting_user_id`.
This better shows the situation for message edits, where we use the same
class.
2021-06-25 08:54:00 -07:00
Abhijeet Prasad Bodas 1cf1d147aa event_queue: Move notification trigger logic to notification_data.
This removes some complexity from the event_queue module.
To avoid code duplication, we reduce the `is_notifiable` methods to
internally just call the `trigger` methods and check their return value.
2021-06-24 09:35:18 -07:00
Abhijeet Prasad Bodas 66192825c0 maybe_enqueue_notifications: Take in notification_data dataclass.
* Modify `maybe_enqueue_notifications` to take in an instance of the
dataclass introduced in 951b49c048.

* The `check_notify` tests tested the "when to notify" logic in a way
which involved `maybe_enqueue_notifications`. To simplify things, we've
earlier extracted this logic in 8182632d7e.
So, we just kill off the `check_notify` test, and keep only those parts
which verify the queueing and return value behavior of that funtion.

* We retain the the missedmessage_hook and message
message_edit_notifications since they are more integration-style.

* There's a slightly subtle change with the missedmessage_hook tests.
Before this commit, we short-circuited the hook if the sender was muted
(5a642cea11).
With this commit, we delegate the check to our dataclass methods.
So, `maybe_enqueue_notifications` will be called even if the sender was
muted, and the test needs to be updated.

* In our test helper `get_maybe_enqueue_notifications_parameters` which
generates default values for testing `maybe_enqueue_notifications` calls,
we keep `message_id`, `sender_id`, and `user_id` as required arguments,
so that the tests are super-clear and avoid accidental false positives.

* Because `do_update_embedded_data` also sends `update_message` events,
we deal with that case with some hacky code for now. See the comment
there.

This mostly completes the extraction of the "when to notify" logic into
our new `notification_data` module.
2021-06-24 09:35:17 -07:00
Abhijeet Prasad Bodas dedc39f139 notifications_data: Rename `id` -> `user_id`.
We also make this a mandatory named argument for our test helper
for clarity.
2021-06-24 17:34:50 +05:30
Abhijeet Prasad Bodas f6e705d477 maybe_enqueue_notifications: Require all keyword arguments.
This is a more readable way to call the function.
2021-06-24 17:34:50 +05:30
Abhijeet Prasad Bodas 226ac4bd3b tornado: Use `UserMessageNotificationsData` for update_message.
This lets us simplify what had previously been somewhat duplicated
logic between the send and edit code paths.
2021-06-22 10:27:59 -07:00
Abhijeet Prasad Bodas c3fb413119 message edit: Don't send mentioned user_ids in event dict.
We already have this data in the `flags` for each user, so no need to
send this set/list in the event dictionary.

The `flags` in the event dict represent the after-message-update state,
so we can't avoid sending `prior_mention_user_ids`.
2021-06-22 10:27:55 -07:00
Abhijeet Prasad Bodas c6d696cf61 process_message_event: Deduplicate `is_notifiable` logic.
We use the `UserMessageNotificationsData` methods to check if the
message is notifiable, and use a cleaner early continue pattern.
2021-06-21 10:52:59 -07:00
Abhijeet Prasad Bodas aeb2ad5f46 notification_data: Annotate `flags` with `Collection`.
Since `flags` here could be iterated through multiple times
(to check for push/email notifiability), we use `Collection`.
Inspired by 871e73ab8f.

The other change here in the `event_queue` code is prep for using
the `UserMessageNotificationsData` class there.
2021-06-21 10:52:59 -07:00
Abhijeet Prasad Bodas ed58393079 message send: Optimize how user data is sent to Tornado.
Before this commit, we used to pre-calculate flags for user data and send
it to Tornado, like so:
```
{
    "id": 10,
    "flags": ["mentioned"],
    "mentioned": true,
    "online_push_enabled": false,
    "stream_push_notify": false,
    "stream_email_notify": false,
    "wildcard_mention_notify": false,
    "sender_is_muted": false,
}
```

This has the benefit of simplifying the logic in the event_queue code a bit.

However, because we sent such an object for each user receiving the event,
the string keys (like "stream_email_notify") get duplicated in the JSON
blob that is sent to Tornado.

For 1000 users, this data may take up upto ~190KB of space, which can
cause performance degradation in large organisations.

Hence, as an alternative, we send just the list of user_ids fitting
each notification criteria, and then calculate the flags in Tornado.
This brings down the space to ~60KB for 1000 users.

This commit reverts parts of following commits:
- 2179275
- 40cd6b5

We will in the future, add helpers to create `UserMessageNotificationsData`
objects from these lists, so as to avoid code duplication.
2021-06-21 10:52:59 -07:00
Abhijeet Prasad Bodas 6167c36adc event_queue: Translation code for user data migration.
This is separate from the next commit for ease of testing.
To verify that the compatibility code works correctly, all message send
and event_queue tests from our test suite should pass on just this commit.
2021-06-21 10:52:59 -07:00
Abhijeet Prasad Bodas 3ff3ded1ae process_message_event: Always calculate `online_push_enabled`.
Unlike `receiver_is_off_zulip`, fetching from a dict is pretty cheap,
so we can calculate `online_push_enabled` along with the other
variables.

This is a prep change to start using the dataclass introduced in the
earlier commit in this code.
2021-06-15 12:30:31 -07:00
Abhijeet Prasad Bodas 2179275020 event_queue: Deduplicate `mentioned` flag calculation.
This gives us a single place where all user data for the message
send event is calculated, and is a prep change for introducing
a TypedDict or dataclass to keep this data toghether.
2021-06-15 12:30:31 -07:00
Abhijeet Prasad Bodas 40cd6b5440 message send: Calculate `wildcard_mention_notify` pre-send_event.
This deduplicates some logic, and makes it so that
`wildcard_mention_notify` always contains what its name says it does.
2021-06-15 12:30:31 -07:00
Abhijeet Prasad Bodas 5a642cea11 missedmessage_hook: Don't enqueue notificationss if sender is muted.
This is a follow up to 71742dce24 to handle
muted senders in the missedmessage_hook too.
2021-06-15 12:30:31 -07:00
Abhijeet Prasad Bodas 86a20c5b3c event queue: Always set internal_data flags.
We have already calculated these values, so storing them should not cause
significant performance degradation.

This is a prep chenge for sending a few more flags through internal_data,
namely if `sender_is_muted`.
2021-06-15 12:30:31 -07:00
Abhijeet Prasad Bodas 10dd5f784b event_queue: Don't check for "read" flag when processing events.
* In `event_queue.py`, only the sender and recipient users who have muted
the sender will have the "read" flag set.

* We already skip enqueueing notifications for users who've muted the sender
after 58da384da3.

* The queue consume functions for email and push notifications already
check filter messages which have been read before sending notifications.

* So, the "read" logic in `event_queue.py` is unnecessary, and the
processing power saved from not enqueueing notifications for a single
user should be insignificant, so we remove these checks all toghether.
2021-06-11 08:07:37 -07:00
Abhijeet Prasad Bodas c6a31dcd9f event_queue: Extract local variables. 2021-06-11 08:05:27 -07:00
Abhijeet Prasad Bodas 58da384da3 muting: Don't enqueue notifications for messages from muted senders.
Earlier, the notification-blocking for messages from muted senders
was a side-effect of we never sending notifications for messages
with the "read" flag.

This commit decouples these two things, as a prep for having new
settings which will allow users to **always** receive email
notifications, including when/if they read the message during the
time the notifications is in the queue.

We still mark muted-sender messages as "read" when they are sent,
because that's desirable anyways.
2021-06-08 14:58:14 -07:00
Tim Abbott d84d61f718 mypy: Fix user_id typo in maybe_enqueue_notifications_for_message_update.
This also lets us remove importing UserProfile at all in this module.
2021-06-07 13:31:54 -07:00
Abhijeet Prasad Bodas 5f5323be7d event_queue: Pass `bool`s to `maybe_enqueue_for_message_update`.
This simplifies the logic in the function itself and makes this function
consistent with how we pass data to `maybe_enqueue_notifications`.
2021-06-07 13:29:37 -07:00
Abhijeet Prasad Bodas 22d19375f2 event_queue: Reorder `maybe_enqueue_for_update` parameters.
This will make `maybe_enqueue_notifications_for_message_update`'s
arguments more consistent with `maybe_enqueue_notifications`.
2021-06-07 19:54:04 +05:30
Abhijeet Prasad Bodas f236a0d10d message send: Rename `always_push_notify` -> `online_push_enabled`.
This is a better name, since it clearly denotes a user
configured setting.
2021-05-26 15:19:32 -07:00
Abhijeet Prasad Bodas ddd123f133 message send: Rename `push_notify_user_ids` -> `online_push_user_ids`.
The old name `push_notify_user_ids` was misleading, because
it does not contain user ids which should be notified for
the current message, but rather user ids who have the online
push notifications setting enabled.

When the Tornado server is restarted during an upgrade, if
server has old events with the `push_notify_user_ids` fields,
the server will throw error after this rename. Hence, we need
to explicitly handle such cases while processing the event.
2021-05-26 15:13:08 -07:00
orientor ac203cd9f1 middleware: Add client_version attribute to request. 2021-04-29 17:03:40 -07:00
orientor 6224d83dea middleware: Get client name in LogRequests instead of process_client.
This ensures it is present for all requests; while that was already
essentially true via process_client being called from every standard
decorator, this allows middleware and other code to rely on this
having been set.
2021-04-29 17:03:05 -07:00
Anders Kaseorg 871e73ab8f mypy: Don’t use Iterable for values iterated multiple times.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-04-29 16:06:17 -07:00
m-e-l-u-h-a-n 65c400e06d api: Add zulip_version and zulip_feature_level in restart event.
This help mobile and terminal clients understand whether a server
restart changed API feature levels or not, which in turn determines
whether they will need to resynchronize their data.

Also add tests and documentation for this previously undocumented
event type.

Fixes: #18205.
2021-04-29 12:08:15 -07:00
Dinesh 27e4f5da92 typing: Support sending stream/topic typing status.
This extends the /json/typing endpoint to also accept
stream_id and topic. With this change, the requests
sent to /json/typing should have these:
* `to`: a list set to
    - recipients for a PM
    - stream_id for a stream message
* `topic`, in case of stream message
along with `op`(start or stop).

On receiving a request with stream_id and topic, we send
typing events to clients with stream_typing_notifications set
to True for all users subscribed to that stream.
2021-04-27 20:52:21 -07:00
Dinesh 734d935d4a client_capabilities: Add stream_typing_notifications. 2021-04-27 20:52:21 -07:00
Anders Kaseorg 6060d0d364 docs: Add missing space to compound verbs “log in”, “set up”, etc.
Noun: backup, checkout, cleanup, login, logout, setup, shutdown, signup,
timeout.

Verb: back up, check out, clean up, log in, log out, set up, shut
down, sign up, time out.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-04-26 09:31:08 -07:00
Tim Abbott 48d99886fd event_queue: Update rule for when we can remove compatibility code.
Since c3a8a15bae removed the last
instance of code using the dictionary code path, we actually need to
wait until one can no longer upgrade directly from 4.x to master in
order to avoid breakage should we remove this compatibility code,
since only today did we stop generating the old event format.
2021-04-16 09:58:21 -07:00