-
Notifications
You must be signed in to change notification settings - Fork 598
MSC4140: update error responses #19539
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
Changes from 20 commits
c2d1039
c70c428
3b51b48
ac2bed9
e02f554
2e01d7f
79a0218
a614ebb
448bf17
43e14e9
f69ddc1
437a034
5dfc8b8
1b19c13
267a7e5
df09f8d
3804db0
184b32d
c19df5d
377cac4
0b0aab1
d62f440
4a9464c
79a6f31
34c5ce9
2eea7f5
87ce5f3
e1a0ba4
1a2895b
7bc51d7
56439ef
d2e84b7
af16899
24a543a
b6e61ef
2278272
d805c4d
5390153
a3d0def
45b6fc9
da30132
bcd5b61
80b47aa
06a6a9e
ba17cda
17d1bfe
2f0a302
4e0f0bc
2b41710
ce02497
c73d85f
4a61644
73513bd
71942b0
287eedf
c186d1d
bf70a71
dce57e5
5cd7c10
e828384
43ebc76
5208473
0859de0
c33d443
b384bb8
0cab550
c5b8248
4c597e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| [MSC4140: Cancellable delayed events](https://github.com/matrix-org/matrix-spec-proposals/pull/4140): Update error responses to match their format in the current draft of the MSC. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| [MSC4140: Cancellable delayed events](https://github.com/matrix-org/matrix-spec-proposals/pull/4140): Limit how many delayed events a user may have scheduled at once. |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |||||||||||
| """Tests REST events for /rooms paths.""" | ||||||||||||
|
|
||||||||||||
| import json | ||||||||||||
| import math | ||||||||||||
| from http import HTTPStatus | ||||||||||||
| from typing import Any, Iterable, Literal | ||||||||||||
| from unittest.mock import AsyncMock, Mock, call, patch | ||||||||||||
|
|
@@ -2503,7 +2504,10 @@ def test_send_delayed_invalid_event(self) -> None: | |||||||||||
| {}, | ||||||||||||
| ) | ||||||||||||
| self.assertEqual(HTTPStatus.BAD_REQUEST, channel.code, channel.result) | ||||||||||||
| self.assertNotIn("org.matrix.msc4140.errcode", channel.json_body) | ||||||||||||
| self.assertTrue( | ||||||||||||
| channel.json_body.get("errcode", "").startswith("M_"), | ||||||||||||
| channel.json_body, | ||||||||||||
| ) | ||||||||||||
|
MadLittleMods marked this conversation as resolved.
Outdated
|
||||||||||||
|
|
||||||||||||
| def test_delayed_event_unsupported_by_default(self) -> None: | ||||||||||||
| """Test that sending a delayed event is unsupported with the default config.""" | ||||||||||||
|
|
@@ -2516,11 +2520,26 @@ def test_delayed_event_unsupported_by_default(self) -> None: | |||||||||||
| {"body": "test", "msgtype": "m.text"}, | ||||||||||||
| ) | ||||||||||||
| self.assertEqual(HTTPStatus.BAD_REQUEST, channel.code, channel.result) | ||||||||||||
| self.assertEqual( | ||||||||||||
| "M_MAX_DELAY_UNSUPPORTED", | ||||||||||||
| channel.json_body.get("org.matrix.msc4140.errcode"), | ||||||||||||
| channel.json_body, | ||||||||||||
|
|
||||||||||||
| @unittest.override_config( | ||||||||||||
| { | ||||||||||||
| "max_event_delay_duration": "24h", | ||||||||||||
| "experimental_features": { | ||||||||||||
| "msc4140_max_delayed_events_per_user": 0, | ||||||||||||
| }, | ||||||||||||
| } | ||||||||||||
| ) | ||||||||||||
| def test_delayed_event_disabled_by_limit(self) -> None: | ||||||||||||
| """Test that delayed events are disabled by configuring the per-user limit to 0.""" | ||||||||||||
| channel = self.make_request( | ||||||||||||
| "PUT", | ||||||||||||
| ( | ||||||||||||
| "rooms/%s/send/m.room.message/mid1?org.matrix.msc4140.delay=2000" | ||||||||||||
| % self.room_id | ||||||||||||
| ).encode("ascii"), | ||||||||||||
| {"body": "test", "msgtype": "m.text"}, | ||||||||||||
| ) | ||||||||||||
| self.assertEqual(HTTPStatus.BAD_REQUEST, channel.code, channel.result) | ||||||||||||
|
|
||||||||||||
| @unittest.override_config({"max_event_delay_duration": "1000"}) | ||||||||||||
| def test_delayed_event_exceeds_max_delay(self) -> None: | ||||||||||||
|
|
@@ -2535,10 +2554,66 @@ def test_delayed_event_exceeds_max_delay(self) -> None: | |||||||||||
| ) | ||||||||||||
| self.assertEqual(HTTPStatus.BAD_REQUEST, channel.code, channel.result) | ||||||||||||
| self.assertEqual( | ||||||||||||
| "M_MAX_DELAY_EXCEEDED", | ||||||||||||
| channel.json_body.get("org.matrix.msc4140.errcode"), | ||||||||||||
| Codes.INVALID_PARAM, | ||||||||||||
| channel.json_body.get("errcode"), | ||||||||||||
| channel.json_body, | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| @unittest.override_config( | ||||||||||||
| { | ||||||||||||
| "max_event_delay_duration": "24h", | ||||||||||||
| "experimental_features": { | ||||||||||||
| "msc4140_max_delayed_events_per_user": 1, | ||||||||||||
| }, | ||||||||||||
| } | ||||||||||||
| ) | ||||||||||||
| def test_delayed_event_user_limit_exceeded(self) -> None: | ||||||||||||
| """Test that users cannot have more delayed events scheduled at once than allowed.""" | ||||||||||||
| send_after_ms = 15000 | ||||||||||||
| args = ( | ||||||||||||
| "POST", | ||||||||||||
| ( | ||||||||||||
| f"rooms/%s/send/m.room.message?org.matrix.msc4140.delay={send_after_ms}" | ||||||||||||
| % self.room_id | ||||||||||||
| ).encode("ascii"), | ||||||||||||
|
Comment on lines
+2591
to
+2594
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this work?
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes it does. The only reason I used %-formatting here was solely for consistency with existing test code. It's also indeed fine to remove Though to reduce the size of this PR, I'd rather do this cleanup in a followup dedicated PR, which could even apply it for other tests. |
||||||||||||
| {"body": "test", "msgtype": "m.text"}, | ||||||||||||
| ) | ||||||||||||
| channel = self.make_request(*args) | ||||||||||||
| self.assertEqual(HTTPStatus.OK, channel.code, channel.result) | ||||||||||||
|
|
||||||||||||
| channel = self.make_request(*args) | ||||||||||||
| self.assertEqual(HTTPStatus.TOO_MANY_REQUESTS, channel.code, channel.result) | ||||||||||||
| self.assertEqual( | ||||||||||||
| Codes.LIMIT_EXCEEDED, | ||||||||||||
| channel.json_body["errcode"], | ||||||||||||
| channel.json_body, | ||||||||||||
| ) | ||||||||||||
| step_ms = 100 # This is the amount of time advanced by a call to make_request | ||||||||||||
|
MadLittleMods marked this conversation as resolved.
Outdated
|
||||||||||||
| expected_retry_after_ms = send_after_ms - step_ms | ||||||||||||
| self.assertEqual( | ||||||||||||
| expected_retry_after_ms, | ||||||||||||
| channel.json_body["retry_after_ms"], | ||||||||||||
| channel.json_body, | ||||||||||||
| ) | ||||||||||||
| retry_header = channel.headers.getRawHeaders("Retry-After") | ||||||||||||
| assert retry_header | ||||||||||||
|
MadLittleMods marked this conversation as resolved.
Outdated
|
||||||||||||
| self.assertSequenceEqual( | ||||||||||||
| [str(math.ceil(expected_retry_after_ms / 1000))], | ||||||||||||
| retry_header, | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| # Confirm that ratelimit overrides do not unblock this kind of limit | ||||||||||||
| self.get_success( | ||||||||||||
| self.hs.get_datastores().main.set_ratelimit_for_user(self.user_id, 0, 0) | ||||||||||||
| ) | ||||||||||||
|
MadLittleMods marked this conversation as resolved.
Outdated
|
||||||||||||
| channel = self.make_request(*args) | ||||||||||||
| self.assertEqual(HTTPStatus.TOO_MANY_REQUESTS, channel.code, channel.result) | ||||||||||||
| self.assertIn("retry_after_ms", channel.json_body) | ||||||||||||
| assert channel.headers.getRawHeaders("Retry-After") | ||||||||||||
|
|
||||||||||||
| self.reactor.advance(expected_retry_after_ms) | ||||||||||||
| channel = self.make_request(*args) | ||||||||||||
| self.assertEqual(HTTPStatus.OK, channel.code, channel.result) | ||||||||||||
|
|
||||||||||||
| @unittest.override_config({"max_event_delay_duration": "24h"}) | ||||||||||||
| def test_delayed_event_with_negative_delay(self) -> None: | ||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explain more why and what do do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
267a7e5 rewords the error message to be a bit more descriptive, and to follow the same format used by similar errors in this module.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the original intentions, I was more looking for something like this:
It seems like ideally, we would have had this kind of structure for delayed event config:
If we're going with
0as a valid value to disable delayed events, I guess the updated error message works ⏩There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That new config does look better, though I'd prefer using a dedicated PR to change it, given that
max_event_delay_durationhas been around for a while now & moving it would be a breaking change.I'd also prefer to keep config suggestions in the documentation instead of error messages, to reduce churn on code changes while the MSC is still unstable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like
msc4140_enabledwas added. Are we interested in getting the config shape correct from the beginning?Generally, we try not to break peoples homeserver config. And changing this later means even more complication for the backwards compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msc4140_enabledisn't a real config key. It's just a computed value to make it easier to have/versionsreport whether delayed events are enabled via the other config keys, done since 0859de0. (It is also used in c33d443.)Which is to say, the config shape has not changed, nor do I intend to change it.