sf-queue-sdk 0.2.0b23__tar.gz → 0.2.0b24__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/PKG-INFO +52 -1
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/README.md +51 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/pyproject.toml +1 -1
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/__init__.py +7 -1
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/client.py +2 -0
- sf_queue_sdk-0.2.0b24/queue_sdk/query.py +22 -0
- sf_queue_sdk-0.2.0b24/queue_sdk/queues/recommendation_queue.py +136 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/types.py +20 -0
- sf_queue_sdk-0.2.0b23/queue_sdk/queues/recommendation_queue.py +0 -72
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/.gitignore +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/__init__.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/email/v1/email_pb2.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/email/v1/email_pb2.pyi +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/tool_assignment/v1/tool_assignment_pb2.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/tool_assignment/v1/tool_assignment_pb2.pyi +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/topic_assignment/v1/topic_assignment_pb2.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/topic_assignment/v1/topic_assignment_pb2.pyi +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/queues/__init__.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/queues/base_queue.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/queues/email_queue.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/queues/pdf_to_image_queue.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/queues/tool_assignment_queue.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/queues/topic_assignment_queue.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/redis_client.py +0 -0
- {sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/sanitize.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sf-queue-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0b24
|
|
4
4
|
Summary: Python SDK for sf-queue - Redis-based queue system
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: redis>=5.0.0
|
|
@@ -384,6 +384,32 @@ print(result.success)
|
|
|
384
384
|
print(result.message_id)
|
|
385
385
|
```
|
|
386
386
|
|
|
387
|
+
### Batch (fire and forget)
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
result = client.recommendations.create_batch([
|
|
391
|
+
{"user_id": "user_1", "topic_id": "topic_1", "limit": 10},
|
|
392
|
+
{"user_id": "user_2", "topic_id": "topic_2"},
|
|
393
|
+
])
|
|
394
|
+
print("Enqueued:", result.message_id)
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Batch (wait for confirmation)
|
|
398
|
+
|
|
399
|
+
```python
|
|
400
|
+
result = client.recommendations.create_batch_and_wait(
|
|
401
|
+
[
|
|
402
|
+
{"user_id": "user_1", "topic_id": "topic_1"},
|
|
403
|
+
{"user_id": "user_2", "topic_id": "topic_2"},
|
|
404
|
+
],
|
|
405
|
+
timeout=60,
|
|
406
|
+
)
|
|
407
|
+
print(result.success)
|
|
408
|
+
print(result.total)
|
|
409
|
+
print(result.successful)
|
|
410
|
+
print(result.failed)
|
|
411
|
+
```
|
|
412
|
+
|
|
387
413
|
### Recommendation Fields
|
|
388
414
|
|
|
389
415
|
| Field | Type | Required | Description |
|
|
@@ -392,6 +418,31 @@ print(result.message_id)
|
|
|
392
418
|
| `topic_id` | `str` | Yes | Topic context for recommendations |
|
|
393
419
|
| `limit` | `Optional[int]` | No | Max recommendations to return |
|
|
394
420
|
|
|
421
|
+
## Query (Direct Key Lookups)
|
|
422
|
+
|
|
423
|
+
Read values directly from Redis by key. These are plain `GET` / `MGET` calls, not queue operations.
|
|
424
|
+
|
|
425
|
+
### Get a single key
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
value = client.query.get("mykey")
|
|
429
|
+
print(value) # str or None
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Get multiple keys
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
values = client.query.get_many(["key1", "key2", "key3"])
|
|
436
|
+
print(values) # list[str | None]
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Query Methods
|
|
440
|
+
|
|
441
|
+
| Method | Return Type | Description |
|
|
442
|
+
|--------|-------------|-------------|
|
|
443
|
+
| `get(key)` | `Optional[str]` | Fetch a single key via Redis GET |
|
|
444
|
+
| `get_many(keys)` | `list[Optional[str]]` | Fetch multiple keys via Redis MGET |
|
|
445
|
+
|
|
395
446
|
## Cleanup
|
|
396
447
|
|
|
397
448
|
```python
|
|
@@ -376,6 +376,32 @@ print(result.success)
|
|
|
376
376
|
print(result.message_id)
|
|
377
377
|
```
|
|
378
378
|
|
|
379
|
+
### Batch (fire and forget)
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
result = client.recommendations.create_batch([
|
|
383
|
+
{"user_id": "user_1", "topic_id": "topic_1", "limit": 10},
|
|
384
|
+
{"user_id": "user_2", "topic_id": "topic_2"},
|
|
385
|
+
])
|
|
386
|
+
print("Enqueued:", result.message_id)
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Batch (wait for confirmation)
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
result = client.recommendations.create_batch_and_wait(
|
|
393
|
+
[
|
|
394
|
+
{"user_id": "user_1", "topic_id": "topic_1"},
|
|
395
|
+
{"user_id": "user_2", "topic_id": "topic_2"},
|
|
396
|
+
],
|
|
397
|
+
timeout=60,
|
|
398
|
+
)
|
|
399
|
+
print(result.success)
|
|
400
|
+
print(result.total)
|
|
401
|
+
print(result.successful)
|
|
402
|
+
print(result.failed)
|
|
403
|
+
```
|
|
404
|
+
|
|
379
405
|
### Recommendation Fields
|
|
380
406
|
|
|
381
407
|
| Field | Type | Required | Description |
|
|
@@ -384,6 +410,31 @@ print(result.message_id)
|
|
|
384
410
|
| `topic_id` | `str` | Yes | Topic context for recommendations |
|
|
385
411
|
| `limit` | `Optional[int]` | No | Max recommendations to return |
|
|
386
412
|
|
|
413
|
+
## Query (Direct Key Lookups)
|
|
414
|
+
|
|
415
|
+
Read values directly from Redis by key. These are plain `GET` / `MGET` calls, not queue operations.
|
|
416
|
+
|
|
417
|
+
### Get a single key
|
|
418
|
+
|
|
419
|
+
```python
|
|
420
|
+
value = client.query.get("mykey")
|
|
421
|
+
print(value) # str or None
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Get multiple keys
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
values = client.query.get_many(["key1", "key2", "key3"])
|
|
428
|
+
print(values) # list[str | None]
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Query Methods
|
|
432
|
+
|
|
433
|
+
| Method | Return Type | Description |
|
|
434
|
+
|--------|-------------|-------------|
|
|
435
|
+
| `get(key)` | `Optional[str]` | Fetch a single key via Redis GET |
|
|
436
|
+
| `get_many(keys)` | `list[Optional[str]]` | Fetch multiple keys via Redis MGET |
|
|
437
|
+
|
|
387
438
|
## Cleanup
|
|
388
439
|
|
|
389
440
|
```python
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"""sf-queue Python SDK - Redis-based queue system."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.2.
|
|
3
|
+
__version__ = "0.2.0b24"
|
|
4
4
|
|
|
5
5
|
from queue_sdk.client import QueueClient
|
|
6
|
+
from queue_sdk.query import QueryClient
|
|
6
7
|
from queue_sdk.types import (
|
|
7
8
|
BatchEmailResponse,
|
|
8
9
|
BatchQueueResponse,
|
|
10
|
+
BatchRecommendationRequestData,
|
|
11
|
+
BatchRecommendationResponse,
|
|
9
12
|
BatchToolAssignmentData,
|
|
10
13
|
BatchTopicAssignmentData,
|
|
11
14
|
ConvertData,
|
|
@@ -25,6 +28,7 @@ from queue_sdk.types import (
|
|
|
25
28
|
|
|
26
29
|
__all__ = [
|
|
27
30
|
"QueueClient",
|
|
31
|
+
"QueryClient",
|
|
28
32
|
"QueueClientConfig",
|
|
29
33
|
"EmailData",
|
|
30
34
|
"EmailButton",
|
|
@@ -35,6 +39,8 @@ __all__ = [
|
|
|
35
39
|
"BatchQueueResponse",
|
|
36
40
|
"RecommendationRequestData",
|
|
37
41
|
"RecommendationResponse",
|
|
42
|
+
"BatchRecommendationRequestData",
|
|
43
|
+
"BatchRecommendationResponse",
|
|
38
44
|
"TopicAssignmentData",
|
|
39
45
|
"BatchTopicAssignmentData",
|
|
40
46
|
"ToolAssignmentData",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""QueueClient - main entry point for the Python SDK."""
|
|
2
2
|
|
|
3
|
+
from queue_sdk.query import QueryClient
|
|
3
4
|
from queue_sdk.queues.email_queue import EmailQueue
|
|
4
5
|
from queue_sdk.queues.pdf_to_image_queue import PdfToImageQueue
|
|
5
6
|
from queue_sdk.queues.recommendation_queue import RecommendationQueue
|
|
@@ -67,6 +68,7 @@ class QueueClient:
|
|
|
67
68
|
self.tool_assignment = ToolAssignmentQueue(self._redis, self._environment)
|
|
68
69
|
self.pdf_to_image = PdfToImageQueue(self._redis, self._environment)
|
|
69
70
|
self.recommendations = RecommendationQueue(self._redis, self._environment)
|
|
71
|
+
self.query = QueryClient(self._redis)
|
|
70
72
|
|
|
71
73
|
def disconnect(self) -> None:
|
|
72
74
|
"""Close the Redis connection."""
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""QueryClient - direct Redis key lookups."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import redis as redis_lib
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class QueryClient:
|
|
9
|
+
"""Direct Redis key lookups (GET, MGET)."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, redis_client: redis_lib.Redis):
|
|
12
|
+
self._redis = redis_client
|
|
13
|
+
|
|
14
|
+
def get(self, key: str) -> Optional[str]:
|
|
15
|
+
"""Fetch a single key from Redis."""
|
|
16
|
+
return self._redis.get(key)
|
|
17
|
+
|
|
18
|
+
def get_many(self, keys: list[str]) -> list[Optional[str]]:
|
|
19
|
+
"""Fetch multiple keys from Redis in a single MGET call."""
|
|
20
|
+
if not keys:
|
|
21
|
+
return []
|
|
22
|
+
return self._redis.mget(*keys)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Recommendation queue with typed methods."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
import redis as redis_lib
|
|
7
|
+
|
|
8
|
+
from queue_sdk.queues.base_queue import BaseQueue
|
|
9
|
+
from queue_sdk.types import (
|
|
10
|
+
BatchRecommendationResponse,
|
|
11
|
+
RecommendationResponse,
|
|
12
|
+
SendResult,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RecommendationQueue(BaseQueue):
|
|
17
|
+
"""Typed methods for creating recommendation requests via the queue."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, redis_client: redis_lib.Redis, environment: str):
|
|
20
|
+
super().__init__(redis_client, environment, "recommendation-requests")
|
|
21
|
+
|
|
22
|
+
def create(
|
|
23
|
+
self,
|
|
24
|
+
user_id: str,
|
|
25
|
+
topic_id: str,
|
|
26
|
+
limit: Optional[int] = None,
|
|
27
|
+
) -> SendResult:
|
|
28
|
+
"""Enqueue a recommendation request (fire and forget)."""
|
|
29
|
+
self._validate(user_id, topic_id)
|
|
30
|
+
payload = self._build_payload(user_id, topic_id, limit)
|
|
31
|
+
message_id = self._enqueue(payload)
|
|
32
|
+
return SendResult(message_id=message_id)
|
|
33
|
+
|
|
34
|
+
def create_and_wait(
|
|
35
|
+
self,
|
|
36
|
+
user_id: str,
|
|
37
|
+
topic_id: str,
|
|
38
|
+
limit: Optional[int] = None,
|
|
39
|
+
timeout: Optional[int] = None,
|
|
40
|
+
) -> RecommendationResponse:
|
|
41
|
+
"""Enqueue a recommendation request and wait for the result."""
|
|
42
|
+
self._validate(user_id, topic_id)
|
|
43
|
+
payload = self._build_payload(user_id, topic_id, limit)
|
|
44
|
+
response = self._enqueue_and_wait(payload, timeout)
|
|
45
|
+
|
|
46
|
+
return RecommendationResponse(
|
|
47
|
+
success=response.success,
|
|
48
|
+
message_id=response.message_id,
|
|
49
|
+
error=response.error,
|
|
50
|
+
processed_at=response.processed_at,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def create_batch(
|
|
54
|
+
self,
|
|
55
|
+
requests: list[dict[str, Any]],
|
|
56
|
+
) -> SendResult:
|
|
57
|
+
"""Enqueue multiple recommendation requests (fire and forget)."""
|
|
58
|
+
self._validate_batch(requests)
|
|
59
|
+
payload = self._build_batch_payload(requests)
|
|
60
|
+
message_id = self._enqueue(payload)
|
|
61
|
+
return SendResult(message_id=message_id)
|
|
62
|
+
|
|
63
|
+
def create_batch_and_wait(
|
|
64
|
+
self,
|
|
65
|
+
requests: list[dict[str, Any]],
|
|
66
|
+
timeout: Optional[int] = None,
|
|
67
|
+
) -> BatchRecommendationResponse:
|
|
68
|
+
"""Enqueue multiple recommendation requests and wait for confirmation."""
|
|
69
|
+
self._validate_batch(requests)
|
|
70
|
+
payload = self._build_batch_payload(requests)
|
|
71
|
+
response = self._enqueue_and_wait(payload, timeout)
|
|
72
|
+
|
|
73
|
+
return BatchRecommendationResponse(
|
|
74
|
+
success=response.success,
|
|
75
|
+
message_id=response.message_id,
|
|
76
|
+
error=response.error,
|
|
77
|
+
processed_at=response.processed_at,
|
|
78
|
+
total=getattr(response, "total", len(requests)),
|
|
79
|
+
successful=getattr(
|
|
80
|
+
response, "successful", len(requests) if response.success else 0
|
|
81
|
+
),
|
|
82
|
+
failed=getattr(response, "failed", 0 if response.success else len(requests)),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def _build_payload(
|
|
86
|
+
self,
|
|
87
|
+
user_id: str,
|
|
88
|
+
topic_id: str,
|
|
89
|
+
limit: Optional[int],
|
|
90
|
+
) -> dict[str, Any]:
|
|
91
|
+
"""Build the recommendation request payload."""
|
|
92
|
+
payload: dict[str, Any] = {
|
|
93
|
+
"userId": user_id,
|
|
94
|
+
"topicId": topic_id,
|
|
95
|
+
"requestedAt": datetime.now(timezone.utc).isoformat(),
|
|
96
|
+
"key": f"{user_id}-{topic_id}",
|
|
97
|
+
}
|
|
98
|
+
if limit is not None:
|
|
99
|
+
payload["limit"] = limit
|
|
100
|
+
return payload
|
|
101
|
+
|
|
102
|
+
def _build_batch_payload(
|
|
103
|
+
self, requests: list[dict[str, Any]]
|
|
104
|
+
) -> dict[str, Any]:
|
|
105
|
+
"""Build the batch recommendation request payload."""
|
|
106
|
+
return {
|
|
107
|
+
"batch": True,
|
|
108
|
+
"requests": [
|
|
109
|
+
self._build_payload(
|
|
110
|
+
r.get("user_id", ""),
|
|
111
|
+
r.get("topic_id", ""),
|
|
112
|
+
r.get("limit"),
|
|
113
|
+
)
|
|
114
|
+
for r in requests
|
|
115
|
+
],
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _validate(user_id: str, topic_id: str) -> None:
|
|
120
|
+
"""Validate the recommendation request."""
|
|
121
|
+
if not user_id:
|
|
122
|
+
raise ValueError("user_id is required")
|
|
123
|
+
if not topic_id:
|
|
124
|
+
raise ValueError("topic_id is required")
|
|
125
|
+
|
|
126
|
+
def _validate_batch(self, requests: list[dict[str, Any]]) -> None:
|
|
127
|
+
"""Validate the batch of recommendation requests."""
|
|
128
|
+
if len(requests) == 0:
|
|
129
|
+
raise ValueError("At least one request is required")
|
|
130
|
+
if len(requests) > 100:
|
|
131
|
+
raise ValueError("Maximum 100 requests allowed per batch")
|
|
132
|
+
for r in requests:
|
|
133
|
+
self._validate(
|
|
134
|
+
r.get("user_id", ""),
|
|
135
|
+
r.get("topic_id", ""),
|
|
136
|
+
)
|
|
@@ -147,6 +147,26 @@ class RecommendationResponse:
|
|
|
147
147
|
processed_at: Optional[str] = None
|
|
148
148
|
|
|
149
149
|
|
|
150
|
+
@dataclass
|
|
151
|
+
class BatchRecommendationRequestData:
|
|
152
|
+
"""Data for multiple recommendation requests."""
|
|
153
|
+
|
|
154
|
+
requests: list[dict]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@dataclass
|
|
158
|
+
class BatchRecommendationResponse:
|
|
159
|
+
"""Response from a processed batch of recommendation requests."""
|
|
160
|
+
|
|
161
|
+
success: bool
|
|
162
|
+
message_id: str
|
|
163
|
+
total: int
|
|
164
|
+
successful: int
|
|
165
|
+
failed: int
|
|
166
|
+
error: Optional[str] = None
|
|
167
|
+
processed_at: Optional[str] = None
|
|
168
|
+
|
|
169
|
+
|
|
150
170
|
@dataclass
|
|
151
171
|
class ConvertData:
|
|
152
172
|
"""Data for a PDF/video to image conversion request."""
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"""Recommendation queue with typed methods."""
|
|
2
|
-
|
|
3
|
-
from datetime import datetime, timezone
|
|
4
|
-
from typing import Any, Optional
|
|
5
|
-
|
|
6
|
-
import redis as redis_lib
|
|
7
|
-
|
|
8
|
-
from queue_sdk.queues.base_queue import BaseQueue
|
|
9
|
-
from queue_sdk.types import RecommendationResponse, SendResult
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class RecommendationQueue(BaseQueue):
|
|
13
|
-
"""Typed methods for creating recommendation requests via the queue."""
|
|
14
|
-
|
|
15
|
-
def __init__(self, redis_client: redis_lib.Redis, environment: str):
|
|
16
|
-
super().__init__(redis_client, environment, "recommendation-requests")
|
|
17
|
-
|
|
18
|
-
def create(
|
|
19
|
-
self,
|
|
20
|
-
user_id: str,
|
|
21
|
-
topic_id: str,
|
|
22
|
-
limit: Optional[int] = None,
|
|
23
|
-
) -> SendResult:
|
|
24
|
-
"""Enqueue a recommendation request (fire and forget)."""
|
|
25
|
-
self._validate(user_id, topic_id)
|
|
26
|
-
payload = self._build_payload(user_id, topic_id, limit)
|
|
27
|
-
message_id = self._enqueue(payload)
|
|
28
|
-
return SendResult(message_id=message_id)
|
|
29
|
-
|
|
30
|
-
def create_and_wait(
|
|
31
|
-
self,
|
|
32
|
-
user_id: str,
|
|
33
|
-
topic_id: str,
|
|
34
|
-
limit: Optional[int] = None,
|
|
35
|
-
timeout: Optional[int] = None,
|
|
36
|
-
) -> RecommendationResponse:
|
|
37
|
-
"""Enqueue a recommendation request and wait for the result."""
|
|
38
|
-
self._validate(user_id, topic_id)
|
|
39
|
-
payload = self._build_payload(user_id, topic_id, limit)
|
|
40
|
-
response = self._enqueue_and_wait(payload, timeout)
|
|
41
|
-
|
|
42
|
-
return RecommendationResponse(
|
|
43
|
-
success=response.success,
|
|
44
|
-
message_id=response.message_id,
|
|
45
|
-
error=response.error,
|
|
46
|
-
processed_at=response.processed_at,
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
def _build_payload(
|
|
50
|
-
self,
|
|
51
|
-
user_id: str,
|
|
52
|
-
topic_id: str,
|
|
53
|
-
limit: Optional[int],
|
|
54
|
-
) -> dict[str, Any]:
|
|
55
|
-
"""Build the recommendation request payload."""
|
|
56
|
-
payload: dict[str, Any] = {
|
|
57
|
-
"userId": user_id,
|
|
58
|
-
"topicId": topic_id,
|
|
59
|
-
"requestedAt": datetime.now(timezone.utc).isoformat(),
|
|
60
|
-
"key": f"{user_id}-{topic_id}",
|
|
61
|
-
}
|
|
62
|
-
if limit is not None:
|
|
63
|
-
payload["limit"] = limit
|
|
64
|
-
return payload
|
|
65
|
-
|
|
66
|
-
@staticmethod
|
|
67
|
-
def _validate(user_id: str, topic_id: str) -> None:
|
|
68
|
-
"""Validate the recommendation request."""
|
|
69
|
-
if not user_id:
|
|
70
|
-
raise ValueError("user_id is required")
|
|
71
|
-
if not topic_id:
|
|
72
|
-
raise ValueError("topic_id is required")
|
|
File without changes
|
|
File without changes
|
{sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/email/v1/email_pb2.py
RENAMED
|
File without changes
|
{sf_queue_sdk-0.2.0b23 → sf_queue_sdk-0.2.0b24}/queue_sdk/generated/queue/email/v1/email_pb2.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|