remote_server: Eliminate separate realms-only code path.

Given that most of the use cases for realms-only code path would
really like to upload audit logs too, and the others would likely
produce a better user experience if they upoaded audit logs, we
should just have a single main code path here i.e.
'send_analytics_to_push_bouncer'.

We still only upload usage statistics according to documented
option, and only from the analytics cron job.

The error handling takes place in 'send_analytics_to_push_bouncer'
itself.
This commit is contained in:
Prakhar Pratyush 2023-12-09 17:59:59 +05:30 committed by Tim Abbott
parent 6f93ab72c0
commit d763fae9d0
9 changed files with 185 additions and 160 deletions

View File

@ -106,4 +106,4 @@ class Command(BaseCommand):
logger.info("Sleeping %d seconds before reporting...", delay)
time.sleep(delay)
send_analytics_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=True)

View File

@ -15,7 +15,7 @@ from corporate.lib.remote_billing_util import (
RemoteBillingIdentityDict,
RemoteBillingUserDict,
)
from zerver.lib.remote_server import send_realms_only_to_push_bouncer
from zerver.lib.remote_server import send_analytics_to_push_bouncer
from zerver.lib.test_classes import BouncerTestCase
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.models import UserProfile
@ -163,7 +163,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
realm = desdemona.realm
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
result = self.execute_remote_billing_authentication_flow(desdemona)
@ -193,14 +193,14 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
# and successfully completing the flow - transparently to the user.
self.assertFalse(RemoteRealm.objects.filter(uuid=realm.uuid).exists())
# send_realms_only_to_push_bouncer will be called within the endpoint's
# send_analytics_to_push_bouncer will be called within the endpoint's
# error handling to register realms with the bouncer. We mock.patch it
# to be able to assert that it was called - but also use side_effect
# to maintain the original behavior of the function, instead of
# replacing it with a Mock.
with mock.patch(
"zerver.views.push_notifications.send_realms_only_to_push_bouncer",
side_effect=send_realms_only_to_push_bouncer,
"zerver.views.push_notifications.send_analytics_to_push_bouncer",
side_effect=send_analytics_to_push_bouncer,
) as m:
result = self.execute_remote_billing_authentication_flow(desdemona)
@ -219,7 +219,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
desdemona = self.example_user("desdemona")
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
result = self.execute_remote_billing_authentication_flow(
desdemona,
@ -235,7 +235,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
desdemona = self.example_user("desdemona")
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
with self.settings(TERMS_OF_SERVICE_VERSION="1.0"):
result = self.execute_remote_billing_authentication_flow(
@ -280,7 +280,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
realm = desdemona.realm
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
with time_machine.travel(now, tick=False):
result = self.execute_remote_billing_authentication_flow(desdemona)
@ -336,7 +336,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
realm = desdemona.realm
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
# Straight-up access without authing at all:
result = self.client_get(f"/realm/{realm.uuid!s}/plans/", subdomain="selfhosting")
@ -388,7 +388,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
realm = desdemona.realm
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
result = self.execute_remote_billing_authentication_flow(desdemona, "sponsorship")
@ -408,7 +408,7 @@ class RemoteBillingAuthenticationTest(BouncerTestCase):
realm = desdemona.realm
self.add_mock_response()
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
result = self.execute_remote_billing_authentication_flow(desdemona, "upgrade")

View File

@ -44,9 +44,8 @@ from zerver.lib.exceptions import ErrorCode, JsonableError
from zerver.lib.message import access_message, huddle_users
from zerver.lib.outgoing_http import OutgoingSession
from zerver.lib.remote_server import (
PushNotificationBouncerServerError,
send_analytics_to_push_bouncer,
send_json_to_push_bouncer,
send_realms_only_to_push_bouncer,
send_to_push_bouncer,
)
from zerver.lib.soft_deactivation import soft_reactivate_if_personal_notification
@ -783,37 +782,9 @@ def initialize_push_notifications() -> None:
if uses_notification_bouncer():
# If we're using the notification bouncer, check if we can
# actually send push notifications.
try:
realms = send_realms_only_to_push_bouncer()
except PushNotificationBouncerServerError: # nocoverage
# 50x errors from the bouncer cannot be addressed by the
# administrator of this server, and may be localized to
# this endpoint; don't rashly mark push notifications as
# disabled when they are likely working perfectly fine.
return
except Exception:
# An exception was thrown trying to ask the bouncer service whether we can send
# push notifications or not. There may be certain transient failures that we could
# ignore here, but the default explanation is that there is something wrong either
# with our credentials being corrupted or our ability to reach the bouncer service
# over the network, so we immediately move to reporting push notifications as likely not working,
# as whatever failed here is likely to also fail when trying to send a push notification.
for realm in Realm.objects.filter(push_notifications_enabled=True):
do_set_realm_property(realm, "push_notifications_enabled", False, acting_user=None)
do_set_push_notifications_enabled_end_timestamp(realm, None, acting_user=None)
logger.exception("Exception while sending realms only data to push bouncer")
return
for realm_uuid, data in realms.items():
realm = Realm.objects.get(uuid=realm_uuid)
do_set_realm_property(
realm, "push_notifications_enabled", data["can_push"], acting_user=None
)
do_set_push_notifications_enabled_end_timestamp(
realm, data["expected_end_timestamp"], acting_user=None
)
# actually send push notifications, and update our
# understanding of that state for each realm accordingly.
send_analytics_to_push_bouncer(consider_usage_statistics=False)
return
logger.warning( # nocoverage

View File

@ -11,6 +11,10 @@ from pydantic import UUID4, BaseModel, ConfigDict, Field, Json, field_validator
from analytics.models import InstallationCount, RealmCount
from version import API_FEATURE_LEVEL, ZULIP_VERSION
from zerver.actions.realm_settings import (
do_set_push_notifications_enabled_end_timestamp,
do_set_realm_property,
)
from zerver.lib.exceptions import (
JsonableError,
MissingRemoteRealmError,
@ -18,7 +22,6 @@ from zerver.lib.exceptions import (
)
from zerver.lib.outgoing_http import OutgoingSession
from zerver.lib.queue import queue_json_publish
from zerver.lib.types import RemoteRealmDictValue
from zerver.models import OrgTypeEnum, Realm, RealmAuditLog
@ -311,7 +314,7 @@ def get_realms_info_for_push_bouncer(realm_id: Optional[int] = None) -> List[Rea
return realm_info_list
def send_analytics_to_push_bouncer() -> None:
def send_analytics_to_push_bouncer(consider_usage_statistics: bool = True) -> None:
logger = logging.getLogger("zulip.analytics")
# first, check what's latest
try:
@ -326,7 +329,10 @@ def send_analytics_to_push_bouncer() -> None:
last_acked_installation_count_id = result["last_installation_count_id"]
last_acked_realmauditlog_id = result["last_realmauditlog_id"]
if settings.SUBMIT_USAGE_STATISTICS:
if settings.SUBMIT_USAGE_STATISTICS and consider_usage_statistics:
# Only upload usage statistics, which is relatively expensive,
# if called from the analytics cron job and the server has
# uploading such statistics enabled.
installation_count_query = InstallationCount.objects.filter(
id__gt=last_acked_installation_count_id
)
@ -353,32 +359,48 @@ def send_analytics_to_push_bouncer() -> None:
api_feature_level=API_FEATURE_LEVEL,
)
# Send the actual request, and process the response.
try:
send_to_push_bouncer("POST", "server/analytics", request.model_dump(round_trip=True))
except JsonableError as e:
logger.warning(e.msg)
logger.info("Reported %d records", record_count)
response = send_to_push_bouncer(
"POST", "server/analytics", request.model_dump(round_trip=True)
)
except PushNotificationBouncerServerError: # nocoverage
# 50x errors from the bouncer cannot be addressed by the
# administrator of this server, and may be localized to
# this endpoint; don't rashly mark push notifications as
# disabled when they are likely working perfectly fine.
return
except Exception as e:
if isinstance(e, JsonableError):
# Log exceptions with server error messages to the analytics log.
logger.warning(e.msg)
# An exception was thrown trying to ask the bouncer service whether we can send
# push notifications or not. There may be certain transient failures that we could
# ignore here, but the default explanation is that there is something wrong either
# with our credentials being corrupted or our ability to reach the bouncer service
# over the network, so we immediately move to reporting push notifications as likely not working,
# as whatever failed here is likely to also fail when trying to send a push notification.
for realm in Realm.objects.filter(push_notifications_enabled=True):
do_set_realm_property(realm, "push_notifications_enabled", False, acting_user=None)
do_set_push_notifications_enabled_end_timestamp(realm, None, acting_user=None)
if not isinstance(e, JsonableError):
# Log this generic error only if we haven't already logged specific error above.
logger.exception("Exception asking push bouncer if notifications will work.")
return
def send_realms_only_to_push_bouncer() -> Dict[str, RemoteRealmDictValue]:
request = AnalyticsRequest.model_construct(
realm_counts=[],
installation_counts=[],
realms=get_realms_info_for_push_bouncer(),
version=ZULIP_VERSION,
api_feature_level=API_FEATURE_LEVEL,
)
# We don't catch JsonableError here, because we want it to propagate further
# to either explicitly, loudly fail or be error-handled by the caller.
response = send_to_push_bouncer(
"POST",
"server/analytics",
request.model_dump(round_trip=True, exclude={"realmauditlog_rows"}),
)
assert isinstance(response["realms"], dict) # for mypy
realms = response["realms"]
for realm_uuid, data in realms.items():
realm = Realm.objects.get(uuid=realm_uuid)
do_set_realm_property(
realm, "push_notifications_enabled", data["can_push"], acting_user=None
)
do_set_push_notifications_enabled_end_timestamp(
realm, data["expected_end_timestamp"], acting_user=None
)
return response["realms"]
logger.info("Reported %d records", record_count)
def enqueue_register_realm_with_push_bouncer_if_needed(realm: Realm) -> None:

View File

@ -1399,14 +1399,28 @@ class RealmImportExportTest(ExportFile):
with self.settings(BILLING_ENABLED=False), self.assertLogs(level="INFO"), patch(
"zerver.lib.remote_server.send_to_push_bouncer"
) as m:
get_response = {
"last_realm_count_id": 0,
"last_installation_count_id": 0,
"last_realmauditlog_id": 0,
}
def mock_send_to_push_bouncer_response( # type: ignore[return]
method: str, *args: Any
) -> Optional[Dict[str, int]]:
if method == "GET":
return get_response
m.side_effect = mock_send_to_push_bouncer_response
new_realm = do_import_realm(get_output_dir(), "test-zulip")
self.assertTrue(Realm.objects.filter(string_id="test-zulip").exists())
calls_args_for_assert = m.call_args_list[0][0]
calls_args_for_assert = m.call_args_list[1][0]
self.assertEqual(calls_args_for_assert[0], "POST")
self.assertEqual(calls_args_for_assert[1], "server/analytics")
self.assertIn(
new_realm.id, [realm["id"] for realm in json.loads(m.call_args_list[0][0][2]["realms"])]
new_realm.id, [realm["id"] for realm in json.loads(m.call_args_list[1][0][2]["realms"])]
)
def test_import_files_from_local(self) -> None:

View File

@ -24,7 +24,7 @@ from typing_extensions import override
from analytics.lib.counts import CountStat, LoggingCountStat
from analytics.models import InstallationCount, RealmCount
from corporate.models import CustomerPlan
from version import API_FEATURE_LEVEL, ZULIP_VERSION
from version import ZULIP_VERSION
from zerver.actions.message_delete import do_delete_messages
from zerver.actions.message_flags import do_mark_stream_messages_as_read, do_update_message_flags
from zerver.actions.realm_settings import (
@ -67,7 +67,6 @@ from zerver.lib.remote_server import (
build_analytics_data,
get_realms_info_for_push_bouncer,
send_analytics_to_push_bouncer,
send_realms_only_to_push_bouncer,
send_to_push_bouncer,
)
from zerver.lib.response import json_response_from_error
@ -780,30 +779,29 @@ class PushBouncerNotificationTest(BouncerTestCase):
with mock.patch(
"zerver.lib.push_notifications.uses_notification_bouncer", return_value=True
):
realms_response = {realm.uuid: {"can_push": True, "expected_end_timestamp": None}}
with mock.patch(
"zerver.lib.push_notifications.send_realms_only_to_push_bouncer",
return_value=realms_response,
):
with mock.patch("zerver.lib.remote_server.send_to_push_bouncer") as m:
post_response = {
"realms": {realm.uuid: {"can_push": True, "expected_end_timestamp": None}}
}
get_response = {
"last_realm_count_id": 0,
"last_installation_count_id": 0,
"last_realmauditlog_id": 0,
}
def mock_send_to_push_bouncer_response(method: str, *args: Any) -> Dict[str, Any]:
if method == "POST":
return post_response
return get_response
m.side_effect = mock_send_to_push_bouncer_response
initialize_push_notifications()
realm = get_realm("zulip")
self.assertTrue(realm.push_notifications_enabled)
self.assertEqual(realm.push_notifications_enabled_end_timestamp, None)
with mock.patch(
"zerver.lib.push_notifications.send_realms_only_to_push_bouncer",
side_effect=Exception,
), self.assertLogs("zerver.lib.push_notifications", level="ERROR") as exception_log:
initialize_push_notifications()
realm = get_realm("zulip")
self.assertFalse(realm.push_notifications_enabled)
self.assertIn(
"ERROR:zerver.lib.push_notifications:Exception while sending realms only data to push bouncer",
exception_log.output[0],
)
@override_settings(PUSH_NOTIFICATION_BOUNCER_URL="https://push.zulip.org.example.com")
@responses.activate
def test_register_token_realm_uuid_belongs_to_different_server(self) -> None:
@ -1044,10 +1042,6 @@ class AnalyticsBouncerTest(BouncerTestCase):
self.add_mock_response()
# Send any existing data over, so that we can start the test with a "clean" slate
audit_log = RealmAuditLog.objects.all().order_by("id").last()
assert audit_log is not None
audit_log_max_id = audit_log.id
remote_server = RemoteZulipServer.objects.get(uuid=self.server_uuid)
assert remote_server is not None
assert remote_server.last_version is None
@ -1055,6 +1049,10 @@ class AnalyticsBouncerTest(BouncerTestCase):
send_analytics_to_push_bouncer()
self.assertTrue(responses.assert_call_count(ANALYTICS_STATUS_URL, 1))
audit_log = RealmAuditLog.objects.all().order_by("id").last()
assert audit_log is not None
audit_log_max_id = audit_log.id
remote_server = RemoteZulipServer.objects.get(uuid=self.server_uuid)
assert remote_server.last_version == ZULIP_VERSION
@ -1126,8 +1124,14 @@ class AnalyticsBouncerTest(BouncerTestCase):
send_analytics_to_push_bouncer()
check_counts(2, 2, 0, 0, 1)
with self.settings(SUBMIT_USAGE_STATISTICS=True):
# With 'SUBMIT_USAGE_STATISTICS=True' but 'consider_usage_statistics=False',
# we don't send RealmCount and InstallationCounts.
send_analytics_to_push_bouncer(consider_usage_statistics=False)
check_counts(3, 3, 0, 0, 1)
send_analytics_to_push_bouncer()
check_counts(3, 3, 1, 1, 1)
check_counts(4, 4, 1, 1, 1)
self.assertEqual(
list(
@ -1204,7 +1208,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
do_deactivate_realm(zephyr_realm, acting_user=None)
send_analytics_to_push_bouncer()
check_counts(4, 4, 1, 1, 7)
check_counts(5, 5, 1, 1, 7)
zephyr_remote_realm = RemoteRealm.objects.get(uuid=zephyr_realm.uuid)
self.assertEqual(zephyr_remote_realm.host, zephyr_realm.host)
@ -1282,7 +1286,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
# Test having no new rows
send_analytics_to_push_bouncer()
check_counts(5, 5, 1, 1, 7)
check_counts(6, 6, 1, 1, 7)
# Test only having new RealmCount rows
RealmCount.objects.create(
@ -1298,14 +1302,14 @@ class AnalyticsBouncerTest(BouncerTestCase):
value=9,
)
send_analytics_to_push_bouncer()
check_counts(6, 6, 3, 1, 7)
check_counts(7, 7, 3, 1, 7)
# Test only having new InstallationCount rows
InstallationCount.objects.create(
property=realm_stat.property, end_time=end_time + timedelta(days=1), value=6
)
send_analytics_to_push_bouncer()
check_counts(7, 7, 3, 2, 7)
check_counts(8, 8, 3, 2, 7)
# Test only having new RealmAuditLog rows
# Non-synced event
@ -1317,7 +1321,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
extra_data={"data": "foo"},
)
send_analytics_to_push_bouncer()
check_counts(8, 8, 3, 2, 7)
check_counts(9, 9, 3, 2, 7)
# Synced event
RealmAuditLog.objects.create(
realm=user.realm,
@ -1329,7 +1333,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
},
)
send_analytics_to_push_bouncer()
check_counts(9, 9, 3, 2, 8)
check_counts(10, 10, 3, 2, 8)
# Now create an InstallationCount with a property that's not supposed
# to be tracked by the remote server - since the bouncer itself tracks
@ -1349,7 +1353,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
)
# The analytics endpoint call counts increase by 1, but the actual RemoteCounts remain unchanged,
# since syncing the data failed.
check_counts(10, 10, 3, 2, 8)
check_counts(11, 11, 3, 2, 8)
forbidden_installation_count.delete()
(realm_count_data, installation_count_data, realmauditlog_data) = build_analytics_data(
@ -1387,7 +1391,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
],
)
# Only the request counts go up -- all of the other rows' duplicates are dropped
check_counts(11, 11, 3, 2, 8)
check_counts(12, 12, 3, 2, 8)
# Test that only valid org_type values are accepted - integers defined in OrgTypeEnum.
realms_data = get_realms_info_for_push_bouncer()
@ -1785,28 +1789,30 @@ class AnalyticsBouncerTest(BouncerTestCase):
@override_settings(PUSH_NOTIFICATION_BOUNCER_URL="https://push.zulip.org.example.com")
@responses.activate
def test_send_realms_only_to_push_bouncer(self) -> None:
def test_realm_properties_after_send_analytics(self) -> None:
self.add_mock_response()
with mock.patch(
"zilencer.views.RemoteRealmBillingSession.get_customer", return_value=None
) as m:
realms = send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
m.assert_called()
for data in realms.values():
self.assertEqual(data["can_push"], True)
self.assertEqual(data["expected_end_timestamp"], None)
realms = Realm.objects.all()
for realm in realms:
self.assertEqual(realm.push_notifications_enabled, True)
self.assertEqual(realm.push_notifications_enabled_end_timestamp, None)
dummy_customer = mock.MagicMock()
with mock.patch(
"zilencer.views.RemoteRealmBillingSession.get_customer", return_value=dummy_customer
):
with mock.patch("zilencer.views.get_current_plan_by_customer", return_value=None) as m:
realms = send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
m.assert_called()
for data in realms.values():
self.assertEqual(data["can_push"], True)
self.assertEqual(data["expected_end_timestamp"], None)
realms = Realm.objects.all()
for realm in realms:
self.assertEqual(realm.push_notifications_enabled, True)
self.assertEqual(realm.push_notifications_enabled_end_timestamp, None)
dummy_customer_plan = mock.MagicMock()
dummy_customer_plan.status = CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE
@ -1820,16 +1826,48 @@ class AnalyticsBouncerTest(BouncerTestCase):
with mock.patch(
"zilencer.views.RemoteRealmBillingSession.get_next_billing_cycle",
return_value=dummy_date,
) as m:
realms = send_realms_only_to_push_bouncer()
) as m, self.assertLogs("zulip.analytics", level="INFO") as info_log:
send_analytics_to_push_bouncer(consider_usage_statistics=False)
m.assert_called()
for data in realms.values():
self.assertEqual(data["can_push"], True)
realms = Realm.objects.all()
for realm in realms:
self.assertEqual(realm.push_notifications_enabled, True)
self.assertEqual(
data["expected_end_timestamp"], datetime_to_timestamp(dummy_date)
realm.push_notifications_enabled_end_timestamp,
dummy_date,
)
self.assertIn(
"INFO:zulip.analytics:Reported 0 records",
info_log.output[0],
)
send_realms_only_to_push_bouncer()
with mock.patch("zerver.lib.remote_server.send_to_push_bouncer") as m, self.assertLogs(
"zulip.analytics", level="ERROR"
) as exception_log:
get_response = {
"last_realm_count_id": 0,
"last_installation_count_id": 0,
"last_realmauditlog_id": 0,
}
def mock_send_to_push_bouncer_response(method: str, *args: Any) -> Dict[str, int]:
if method == "POST":
raise Exception
return get_response
m.side_effect = mock_send_to_push_bouncer_response
send_analytics_to_push_bouncer(consider_usage_statistics=False)
realms = Realm.objects.all()
for realm in realms:
self.assertFalse(realm.push_notifications_enabled)
self.assertIn(
"ERROR:zulip.analytics:Exception asking push bouncer if notifications will work.",
exception_log.output[0],
)
send_analytics_to_push_bouncer(consider_usage_statistics=False)
self.assertEqual(
list(
@ -1859,38 +1897,6 @@ class AnalyticsBouncerTest(BouncerTestCase):
],
)
# Use a mock to assert exactly the data that gets sent.
dummy_send_realms_only_response = {
"result": "success",
"msg": "",
"realms": {
"f9535515-84d0-489e-80d5-9ae97c3c7ec1": {
"can_push": True,
"expected_end_timestamp": None,
},
},
}
with mock.patch(
"zerver.lib.remote_server.send_to_push_bouncer",
return_value=dummy_send_realms_only_response,
) as mock_send_to_push_bouncer:
send_realms_only_to_push_bouncer()
post_data = {
"realm_counts": "[]",
"installation_counts": "[]",
"realms": orjson.dumps(
[dict(realm_data) for realm_data in get_realms_info_for_push_bouncer()]
).decode(),
"version": orjson.dumps(ZULIP_VERSION).decode(),
"api_feature_level": orjson.dumps(API_FEATURE_LEVEL).decode(),
}
mock_send_to_push_bouncer.assert_called_with(
"POST",
"server/analytics",
post_data,
)
class PushNotificationTest(BouncerTestCase):
@override

View File

@ -1089,18 +1089,30 @@ class RealmTest(ZulipTestCase):
}
with mock.patch(
"zerver.lib.remote_server.send_to_push_bouncer",
return_value=dummy_send_realms_only_response,
) as m:
get_response = {
"last_realm_count_id": 0,
"last_installation_count_id": 0,
"last_realmauditlog_id": 0,
}
def mock_send_to_push_bouncer_response(method: str, *args: Any) -> Dict[str, Any]:
if method == "GET":
return get_response
return dummy_send_realms_only_response
m.side_effect = mock_send_to_push_bouncer_response
realm = do_create_realm("realm_string_id", "realm name")
self.assertEqual(realm.string_id, "realm_string_id")
self.assertEqual(m.call_count, 1)
self.assertEqual(m.call_count, 2)
calls_args_for_assert = m.call_args_list[0][0]
calls_args_for_assert = m.call_args_list[1][0]
self.assertEqual(calls_args_for_assert[0], "POST")
self.assertEqual(calls_args_for_assert[1], "server/analytics")
self.assertIn(
realm.id, [realm["id"] for realm in json.loads(m.call_args_list[0][0][2]["realms"])]
realm.id, [realm["id"] for realm in json.loads(m.call_args_list[1][0][2]["realms"])]
)
def test_changing_waiting_period_updates_system_groups(self) -> None:

View File

@ -24,7 +24,7 @@ from zerver.lib.push_notifications import (
from zerver.lib.remote_server import (
UserDataForRemoteBilling,
get_realms_info_for_push_bouncer,
send_realms_only_to_push_bouncer,
send_analytics_to_push_bouncer,
send_to_push_bouncer,
)
from zerver.lib.request import REQ, has_request_variables
@ -162,7 +162,7 @@ def self_hosting_auth_redirect(
result = send_to_push_bouncer("POST", "server/billing", post_data)
except MissingRemoteRealmError:
# Upload realm info and re-try. It should work now.
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
result = send_to_push_bouncer("POST", "server/billing", post_data)
except RemoteRealmServerMismatchError:
return render(request, "zilencer/remote_realm_server_mismatch_error.html", status=403)

View File

@ -80,7 +80,7 @@ from zerver.lib.pysa import mark_sanitized
from zerver.lib.queue import SimpleQueueClient, retry_event
from zerver.lib.remote_server import (
PushNotificationBouncerRetryLaterError,
send_realms_only_to_push_bouncer,
send_analytics_to_push_bouncer,
)
from zerver.lib.send_email import (
EmailNotDeliveredError,
@ -1174,9 +1174,9 @@ class DeferredWorker(QueueProcessingWorker):
# In the future we may use the realm_id to send only that single realm's info.
realm_id = event["realm_id"]
logger.info(
"Running send_realms_only_to_push_bouncer, requested due to realm %s", realm_id
"Running send_analytics_to_push_bouncer, requested due to realm %s", realm_id
)
send_realms_only_to_push_bouncer()
send_analytics_to_push_bouncer(consider_usage_statistics=False)
end = time.time()
logger.info(