Improve performance of generating ActivityPub payloads

For a large number of receivers in `handle_send`.

Only generate payload once and then just copy and attach receivers.
merge-requests/159/merge
Jason Robinson 2019-11-28 21:02:13 +02:00
rodzic e0d818f724
commit 0f7b22bb04
2 zmienionych plików z 19 dodań i 9 usunięć

Wyświetl plik

@ -19,6 +19,10 @@
Previously requirement was 30 seconds, which caused loss of messages where signature validation Previously requirement was 30 seconds, which caused loss of messages where signature validation
didn't happen immediately, but in a background worker which didn't immediately process the job. didn't happen immediately, but in a background worker which didn't immediately process the job.
### Internal changes
* Improve performance of generating ActivityPub payloads for a large number of receivers in `handle_send`.
## [0.18.1] - 2019-10-06 ## [0.18.1] - 2019-10-06
### Changed ### Changed

Wyświetl plik

@ -1,3 +1,4 @@
import copy
import importlib import importlib
import json import json
import logging import logging
@ -114,7 +115,7 @@ def handle_send(
be generated. If given, the payload will be sent as this user. be generated. If given, the payload will be sent as this user.
""" """
payloads = [] payloads = []
public_payloads = { ready_payloads = {
"activitypub": { "activitypub": {
"auth": None, "auth": None,
"payload": None, "payload": None,
@ -143,7 +144,12 @@ def handle_send(
if protocol == "activitypub": if protocol == "activitypub":
try: try:
payload = handle_create_payload(entity, author_user, protocol, parent_user=parent_user) if not ready_payloads[protocol]["payload"]:
# noinspection PyTypeChecker
ready_payloads[protocol]["payload"] = handle_create_payload(
entity, author_user, protocol, parent_user=parent_user,
)
payload = copy.copy(ready_payloads[protocol]["payload"])
if public: if public:
payload["to"] = [NAMESPACE_PUBLIC] payload["to"] = [NAMESPACE_PUBLIC]
payload["cc"] = [fid] payload["cc"] = [fid]
@ -154,13 +160,13 @@ def handle_send(
payload["to"] = [fid] payload["to"] = [fid]
if isinstance(payload.get("object"), dict): if isinstance(payload.get("object"), dict):
payload["object"]["to"] = [fid] payload["object"]["to"] = [fid]
payload = json.dumps(payload).encode("utf-8") rendered_payload = json.dumps(payload).encode("utf-8")
except Exception as ex: except Exception as ex:
logger.error("handle_send - failed to generate payload for %s, %s: %s", fid, endpoint, ex) logger.error("handle_send - failed to generate payload for %s, %s: %s", fid, endpoint, ex)
continue continue
payloads.append({ payloads.append({
"auth": get_http_authentication(author_user.rsa_private_key, f"{author_user.id}#main-key"), "auth": get_http_authentication(author_user.rsa_private_key, f"{author_user.id}#main-key"),
"payload": payload, "payload": rendered_payload,
"content_type": 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', "content_type": 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
"urls": {endpoint}, "urls": {endpoint},
}) })
@ -168,15 +174,15 @@ def handle_send(
if public: if public:
if public_key: if public_key:
raise ValueError("handle_send - Diaspora recipient cannot be public and use encrypted delivery") raise ValueError("handle_send - Diaspora recipient cannot be public and use encrypted delivery")
if not public_payloads[protocol]["payload"]: if not ready_payloads[protocol]["payload"]:
try: try:
# noinspection PyTypeChecker # noinspection PyTypeChecker
public_payloads[protocol]["payload"] = handle_create_payload( ready_payloads[protocol]["payload"] = handle_create_payload(
entity, author_user, protocol, parent_user=parent_user, entity, author_user, protocol, parent_user=parent_user,
) )
except Exception as ex: except Exception as ex:
logger.error("handle_send - failed to generate public payload for %s: %s", endpoint, ex) logger.error("handle_send - failed to generate public payload for %s: %s", endpoint, ex)
public_payloads["diaspora"]["urls"].add(endpoint) ready_payloads["diaspora"]["urls"].add(endpoint)
else: else:
if not public_key: if not public_key:
raise ValueError("handle_send - Diaspora recipient cannot be private without a public key for " raise ValueError("handle_send - Diaspora recipient cannot be private without a public key for "
@ -195,9 +201,9 @@ def handle_send(
}) })
# Add public diaspora payload # Add public diaspora payload
if public_payloads["diaspora"]["payload"]: if ready_payloads["diaspora"]["payload"]:
payloads.append({ payloads.append({
"urls": public_payloads["diaspora"]["urls"], "payload": public_payloads["diaspora"]["payload"], "urls": ready_payloads["diaspora"]["urls"], "payload": ready_payloads["diaspora"]["payload"],
"content_type": "application/magic-envelope+xml", "auth": None, "content_type": "application/magic-envelope+xml", "auth": None,
}) })