Skip to content

Commit e9d4f4d

Browse files
committed
fix: forward idempotency_key, ignore_ssl_errors and do_not_retry in ad-hoc webhooks
1 parent 75d8748 commit e9d4f4d

2 files changed

Lines changed: 25 additions & 33 deletions

File tree

src/apify/_webhook.py

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from crawlee._utils.urls import validate_http_url
88

99
from apify._utils import docs_group
10-
from apify.log import logger
1110

1211
if TYPE_CHECKING:
1312
from apify_client._literals import WebhookEventType
@@ -20,9 +19,6 @@ class Webhook:
2019
2120
The same instance can be passed as an ad-hoc webhook to `Actor.start()` / `Actor.call()` or as a persistent
2221
webhook to `Actor.add_webhook()` (the `condition.actor_run_id` is set automatically to the current run).
23-
24-
Ad-hoc webhooks support only `event_types`, `request_url`, `payload_template` and `headers_template`; the
25-
remaining fields apply only to `Actor.add_webhook()` and are ignored (with a warning) otherwise.
2622
"""
2723

2824
event_types: list[WebhookEventType]
@@ -38,47 +34,32 @@ class Webhook:
3834
"""Template for the HTTP headers sent by the webhook."""
3935

4036
idempotency_key: str | None = None
41-
"""Key that prevents creating duplicate webhooks. Only applies to `Actor.add_webhook()`."""
37+
"""Key that prevents creating duplicate webhooks."""
4238

4339
ignore_ssl_errors: bool | None = None
44-
"""Whether to ignore SSL errors when sending the request. Only applies to `Actor.add_webhook()`."""
40+
"""Whether to ignore SSL errors when sending the request."""
4541

4642
do_not_retry: bool | None = None
47-
"""Whether to skip retrying the request on failure. Only applies to `Actor.add_webhook()`."""
43+
"""Whether to skip retrying the request on failure."""
4844

4945
def __post_init__(self) -> None:
5046
# Fail fast on a malformed URL at construction time instead of deferring the error to the API call.
5147
validate_http_url(self.request_url)
5248

5349

5450
def to_client_representations(webhooks: list[Webhook] | None) -> list[WebhookRepresentation] | None:
55-
"""Project SDK webhooks to the minimal ad-hoc representation accepted by the client's `start()` / `call()`.
56-
57-
Fields not supported by ad-hoc webhooks (`idempotency_key`, `ignore_ssl_errors`, `do_not_retry`) are dropped
58-
with a warning.
59-
"""
51+
"""Convert SDK webhooks to the ad-hoc representation accepted by the client's `start()` / `call()`."""
6052
if not webhooks:
6153
return None
62-
63-
for webhook in webhooks:
64-
dropped = [
65-
field
66-
for field in ('idempotency_key', 'ignore_ssl_errors', 'do_not_retry')
67-
if getattr(webhook, field) is not None
68-
]
69-
if dropped:
70-
fields = ', '.join(f'`{field}`' for field in dropped)
71-
logger.warning(
72-
f'Ad-hoc webhooks do not support {fields}; the field(s) will be ignored. '
73-
f'Use `Actor.add_webhook()` to create a webhook with them.'
74-
)
75-
7654
return [
7755
WebhookRepresentation(
7856
event_types=w.event_types,
7957
request_url=w.request_url,
8058
payload_template=w.payload_template,
8159
headers_template=w.headers_template,
60+
idempotency_key=w.idempotency_key,
61+
ignore_ssl_errors=w.ignore_ssl_errors,
62+
do_not_retry=w.do_not_retry,
8263
)
8364
for w in webhooks
8465
]

tests/unit/actor/test_actor_helpers.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,16 @@ async def test_remote_method_with_webhooks(
253253

254254

255255
@pytest.mark.parametrize(('client_resource', 'client_method', 'actor_method_name', 'entity_id'), _ACTOR_REMOTE_METHODS)
256-
async def test_remote_method_warns_on_unsupported_webhook_fields(
256+
async def test_remote_method_forwards_all_webhook_fields(
257257
apify_client_async_patcher: ApifyClientAsyncPatcher,
258258
fake_actor_run: Run,
259259
client_resource: str,
260260
client_method: str,
261261
actor_method_name: str,
262262
entity_id: str,
263-
caplog: pytest.LogCaptureFixture,
264263
) -> None:
265-
"""Test that start/call/call_task warn about `Webhook` fields not supported by ad-hoc webhooks."""
264+
"""Test that start/call/call_task forward all `Webhook` fields to the client representation."""
266265
apify_client_async_patcher.patch(client_resource, client_method, return_value=fake_actor_run)
267-
caplog.set_level('WARNING')
268266

269267
async with Actor:
270268
actor_method = getattr(Actor, actor_method_name)
@@ -274,15 +272,28 @@ async def test_remote_method_warns_on_unsupported_webhook_fields(
274272
Webhook(
275273
event_types=['ACTOR.RUN.SUCCEEDED'],
276274
request_url='https://example.com',
275+
payload_template='{"hello": "world"}',
276+
headers_template='{"Authorization": "Bearer ..."}',
277277
idempotency_key='some-key',
278+
ignore_ssl_errors=True,
278279
do_not_retry=True,
279280
)
280281
],
281282
)
282283

283-
matching = [record for record in caplog.records if 'Ad-hoc webhooks do not support' in record.message]
284-
assert len(matching) == 1
285-
assert '`idempotency_key`, `do_not_retry`' in matching[0].message
284+
calls = apify_client_async_patcher.calls[client_resource][client_method]
285+
assert len(calls) == 1
286+
_, kwargs = calls[0][0], calls[0][1]
287+
(representation,) = kwargs['webhooks']
288+
assert representation.model_dump(by_alias=True, exclude_none=True) == {
289+
'eventTypes': ['ACTOR.RUN.SUCCEEDED'],
290+
'requestUrl': 'https://example.com',
291+
'payloadTemplate': '{"hello": "world"}',
292+
'headersTemplate': '{"Authorization": "Bearer ..."}',
293+
'idempotencyKey': 'some-key',
294+
'ignoreSslErrors': True,
295+
'doNotRetry': True,
296+
}
286297

287298

288299
@pytest.mark.parametrize(('client_resource', 'client_method', 'actor_method_name', 'entity_id'), _ACTOR_REMOTE_METHODS)

0 commit comments

Comments
 (0)