DefStream 0.1.6__tar.gz → 0.1.7__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.
Files changed (95) hide show
  1. {defstream-0.1.6 → defstream-0.1.7}/DefStream.egg-info/PKG-INFO +23 -8
  2. {defstream-0.1.6 → defstream-0.1.7}/DefStream.egg-info/SOURCES.txt +1 -0
  3. {defstream-0.1.6 → defstream-0.1.7}/PKG-INFO +23 -8
  4. {defstream-0.1.6 → defstream-0.1.7}/README.en.md +23 -7
  5. {defstream-0.1.6 → defstream-0.1.7}/README.md +22 -7
  6. {defstream-0.1.6 → defstream-0.1.7}/issues/feature/1/README.md +3 -3
  7. {defstream-0.1.6 → defstream-0.1.7}/issues/fix/3/IMPLEMENTS.md +99 -0
  8. defstream-0.1.7/issues/fix/3/README.md +94 -0
  9. {defstream-0.1.6 → defstream-0.1.7}/issues/fix/3/REQUIREMENTS.md +27 -1
  10. defstream-0.1.7/issues/fix/3/ci.refs.json +4 -0
  11. {defstream-0.1.6 → defstream-0.1.7}/sample/Worker/RabbitMQ/Worker.py +2 -2
  12. {defstream-0.1.6 → defstream-0.1.7}/sample/Worker/Redis/Sample.py +2 -2
  13. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Connection.py +20 -5
  14. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/__init__.py +4 -2
  15. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/Console.py +4 -15
  16. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Message.py +17 -16
  17. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/__init__.py +2 -2
  18. {defstream-0.1.6 → defstream-0.1.7}/test/test_inspector.py +1 -1
  19. {defstream-0.1.6 → defstream-0.1.7}/test/test_inspector_console.py +2 -2
  20. {defstream-0.1.6 → defstream-0.1.7}/test/test_protocol_contracts.py +116 -0
  21. {defstream-0.1.6 → defstream-0.1.7}/test/test_task_messages.py +120 -21
  22. {defstream-0.1.6 → defstream-0.1.7}/test/test_task_priorities.py +9 -9
  23. defstream-0.1.6/issues/fix/3/README.md +0 -47
  24. {defstream-0.1.6 → defstream-0.1.7}/.github/workflows/ci.yml +0 -0
  25. {defstream-0.1.6 → defstream-0.1.7}/.gitignore +0 -0
  26. {defstream-0.1.6 → defstream-0.1.7}/DefStream.egg-info/dependency_links.txt +0 -0
  27. {defstream-0.1.6 → defstream-0.1.7}/DefStream.egg-info/requires.txt +0 -0
  28. {defstream-0.1.6 → defstream-0.1.7}/DefStream.egg-info/top_level.txt +0 -0
  29. {defstream-0.1.6 → defstream-0.1.7}/LICENSE +0 -0
  30. {defstream-0.1.6 → defstream-0.1.7}/issues/feature/1/IMPLEMENTS.md +0 -0
  31. {defstream-0.1.6 → defstream-0.1.7}/issues/feature/1/REQUIREMENTS.md +0 -0
  32. {defstream-0.1.6 → defstream-0.1.7}/issues/feature/1/TASK.md +0 -0
  33. {defstream-0.1.6 → defstream-0.1.7}/issues/feature/1/ci.refs.json +0 -0
  34. {defstream-0.1.6 → defstream-0.1.7}/sample/Broker/Sample.py +0 -0
  35. {defstream-0.1.6 → defstream-0.1.7}/sample/Worker/RabbitMQ/Client.py +0 -0
  36. {defstream-0.1.6 → defstream-0.1.7}/sample/Worker/RabbitMQ/Tasks.py +0 -0
  37. {defstream-0.1.6 → defstream-0.1.7}/sample/Worker/Sample.py +0 -0
  38. {defstream-0.1.6 → defstream-0.1.7}/setup.cfg +0 -0
  39. {defstream-0.1.6 → defstream-0.1.7}/setup.py +0 -0
  40. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Configuration.py +0 -0
  41. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Consumer.py +0 -0
  42. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Errors.py +0 -0
  43. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Event.py +0 -0
  44. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Implements/__init__.py +0 -0
  45. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Policies.py +0 -0
  46. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Priority.py +0 -0
  47. {defstream-0.1.6 → defstream-0.1.7}/src/Broker/Protocol.py +0 -0
  48. {defstream-0.1.6 → defstream-0.1.7}/src/Descriptor/DataObject.py +0 -0
  49. {defstream-0.1.6 → defstream-0.1.7}/src/Descriptor/Types.py +0 -0
  50. {defstream-0.1.6 → defstream-0.1.7}/src/Descriptor/Value.py +0 -0
  51. {defstream-0.1.6 → defstream-0.1.7}/src/Descriptor/__init__.py +0 -0
  52. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extension.py +0 -0
  53. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/Console.html +0 -0
  54. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/Dashboard.html +0 -0
  55. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/Dashboard.py +0 -0
  56. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/HealthCheck.py +0 -0
  57. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/Metrics.py +0 -0
  58. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/Specifications.py +0 -0
  59. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Extensions/__init__.py +0 -0
  60. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Inspector.py +0 -0
  61. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/Response.py +0 -0
  62. {defstream-0.1.6 → defstream-0.1.7}/src/Inspector/__init__.py +0 -0
  63. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Pattern.py +0 -0
  64. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Array.py +0 -0
  65. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Common.py +0 -0
  66. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Compare.py +0 -0
  67. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Condition.py +0 -0
  68. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/DataObject.py +0 -0
  69. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/DateTime.py +0 -0
  70. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Number.py +0 -0
  71. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Object.py +0 -0
  72. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Size.py +0 -0
  73. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/String.py +0 -0
  74. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/Type.py +0 -0
  75. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Patterns/__init__.py +0 -0
  76. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Validate.py +0 -0
  77. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/Validator.py +0 -0
  78. {defstream-0.1.6 → defstream-0.1.7}/src/Validator/__init__.py +0 -0
  79. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Executor.py +0 -0
  80. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Pool.py +0 -0
  81. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Run.py +0 -0
  82. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Specification.py +0 -0
  83. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Startup.py +0 -0
  84. {defstream-0.1.6 → defstream-0.1.7}/src/Worker/Worker.py +0 -0
  85. {defstream-0.1.6 → defstream-0.1.7}/src/__init__.py +0 -0
  86. {defstream-0.1.6 → defstream-0.1.7}/test/test_dashboard.py +0 -0
  87. {defstream-0.1.6 → defstream-0.1.7}/test/test_dashboard_ui.cjs +0 -0
  88. {defstream-0.1.6 → defstream-0.1.7}/test/test_lifecycle_hooks.py +0 -0
  89. {defstream-0.1.6 → defstream-0.1.7}/test/test_pool_callbacks.py +0 -0
  90. {defstream-0.1.6 → defstream-0.1.7}/test/test_process_signals.py +0 -0
  91. {defstream-0.1.6 → defstream-0.1.7}/test/test_release_workflow.py +0 -0
  92. {defstream-0.1.6 → defstream-0.1.7}/test/test_runner_hooks.py +0 -0
  93. {defstream-0.1.6 → defstream-0.1.7}/test/test_specifications.py +0 -0
  94. {defstream-0.1.6 → defstream-0.1.7}/test/test_worker.py +0 -0
  95. {defstream-0.1.6 → defstream-0.1.7}/test/test_worker_startup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DefStream
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Synchronous message processing with pluggable broker adapters
5
5
  Home-page: https://github.com/yong5eon/DefStream
6
6
  Author: Heo Yongseon
@@ -181,7 +181,7 @@ Worker가 실행 중인 상태에서 다른 터미널에서 실행하세요.
181
181
 
182
182
  ```python
183
183
  from DefStream.Broker.Implements.RabbitMQ import Configuration, Connection
184
- from DefStream.Worker import request, send
184
+ from DefStream.Worker import emit, request
185
185
  from tasks import Add
186
186
 
187
187
 
@@ -193,7 +193,7 @@ connection = Connection(Configuration(
193
193
  ))
194
194
  try:
195
195
  connection.connect()
196
- message_id = send(
196
+ message_id = emit(
197
197
  {'a': 10, 'b': 20},
198
198
  task=Add,
199
199
  broker=connection,
@@ -214,7 +214,7 @@ finally:
214
214
  python client.py
215
215
  ```
216
216
 
217
- `send()`와 `request()`는 **각각 별도의 작업을 발행**합니다. 위 예제는 덧셈을 두 번 실행하며,
217
+ `emit()`와 `request()`는 **각각 별도의 작업을 발행**합니다. 위 예제는 덧셈을 두 번 실행하며,
218
218
  `request()`의 결과는 `30`입니다. `request()`의 제한 시간은 초 단위이고,
219
219
  시간이 초과되어도 이미 전달된 작업은 취소되지 않습니다.
220
220
 
@@ -225,14 +225,20 @@ python client.py
225
225
  | 함수 | 역할 | 연결 관리 |
226
226
  | --- | --- | --- |
227
227
  | `declare(task=..., broker=...)` | 작업의 큐·구독 리소스 선언 | 호출자가 연결·종료 |
228
- | `send(body, task=..., broker=...)` | 작업 목적지로 단방향 메시지 발행 | 호출자가 연결·종료 |
228
+ | `emit(body, task=..., broker=...)` | 작업 목적지로 단방향 메시지 발행 | 호출자가 연결·종료 |
229
229
  | `request(body, task=..., broker=..., timeout=5)` | 작업 결과를 동기 RPC로 요청 | 호출자가 연결·종료; RabbitMQ만 지원 |
230
230
 
231
231
  세 함수는 `DefStream.Worker`에서 가져옵니다. 전달된 연결을 자동으로 열거나 닫지 않으며,
232
- `send()`와 `request()`는 목적지를 자동 선언하지 않습니다.
232
+ `emit()`와 `request()`는 목적지를 자동 선언하지 않습니다.
233
233
  수신 Worker 또는 별도의 준비 단계에서 먼저 `declare()`를 호출하세요.
234
234
  하나의 연결을 같은 소유 스레드에서 여러 발행에 재사용할 수 있습니다.
235
235
 
236
+ 세 함수 모두 공통 `Connection`을 받고, 내부에서 선언·발행·RPC 지원 여부를 확인합니다.
237
+ 지원하지 않는 기능은 `NotImplementedError`로 실패합니다.
238
+ 기존 작업 발행 함수와 연결의 `send`는 `emit`으로 이름이 바뀌었습니다.
239
+ 사용자 정의 브로커의 작업 발행 계약도 `TaskSender.send` 대신 `Emittable.emit`을 사용하세요.
240
+ 큐·Exchange·Stream의 저수준 `Sendable.send()`와 RPC `Callable.call()`은 그대로입니다.
241
+
236
242
  작업 본문은 **문자열 키를 가진 매핑**이어야 하며, 반환값은 어댑터가 직렬화할 수 있어야 합니다.
237
243
  하나의 Worker에서는 같은 큐에 여러 작업을 중복 등록할 수 없습니다.
238
244
  메시지 유형을 보고 여러 `Run` 중 하나를 고르는 방식이 아니라 큐별로 작업을 선택합니다.
@@ -250,7 +256,7 @@ from DefStream.Worker import (
250
256
  Run,
251
257
  declare,
252
258
  request,
253
- send,
259
+ emit,
254
260
  )
255
261
 
256
262
 
@@ -275,7 +281,7 @@ declare(
275
281
  task=Add,
276
282
  broker=broker,
277
283
  )
278
- send(
284
+ emit(
279
285
  {'a': 10, 'b': 20},
280
286
  task=Add,
281
287
  broker=broker,
@@ -315,6 +321,10 @@ result = request(
315
321
  브로커 리소스를 직접 사용할 때의 공통 메서드는 다음과 같습니다.
316
322
  모든 리소스가 모든 메서드를 지원하는 것은 아닙니다.
317
323
 
324
+ 연결의 `exchange()`·`queue()`·`stream()`·`consumer()` 지원 여부는 각각
325
+ `GetExchange`·`GetQueue`·`GetStream`·`GetConsumer`로 `isinstance` 또는 `issubclass`
326
+ 검사할 수 있습니다. 이 계약들은 `DefStream.Broker`에서 가져옵니다.
327
+
318
328
  | 메서드 | 의미 | 제한 시간 단위 |
319
329
  | --- | --- | --- |
320
330
  | `send(body)` | 메시지 발행 | 어댑터별 설정 |
@@ -579,6 +589,11 @@ inspector = Inspector(
579
589
  Inspector 자체는 TLS를 제공하지 않으며 공개 웹 서버가 아닙니다.
580
590
  콘솔의 연결 팩터리는 호출마다 새 연결을 반환해야 하고 Worker 연결을 공유하면 안 됩니다.
581
591
 
592
+ Console의 `broker` 인자는 `DefStream.Broker.BrokerFactory` 계약을 사용합니다.
593
+ 이 계약의 `__call__() -> Connection`은 인자 없이 새 연결을 반환합니다.
594
+ 위의 `create_connection` 같은 함수나 람다도 그대로 전달할 수 있으며,
595
+ 클래스로 구현할 때는 `BrokerFactory`를 상속하고 `__call__`을 구현할 수 있습니다.
596
+
582
597
  ## 브로커 선택과 운영 주의사항
583
598
 
584
599
  | 기능 | RabbitMQ | Redis Streams |
@@ -17,6 +17,7 @@ issues/feature/1/ci.refs.json
17
17
  issues/fix/3/IMPLEMENTS.md
18
18
  issues/fix/3/README.md
19
19
  issues/fix/3/REQUIREMENTS.md
20
+ issues/fix/3/ci.refs.json
20
21
  sample/Broker/Sample.py
21
22
  sample/Worker/Sample.py
22
23
  sample/Worker/RabbitMQ/Client.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DefStream
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Synchronous message processing with pluggable broker adapters
5
5
  Home-page: https://github.com/yong5eon/DefStream
6
6
  Author: Heo Yongseon
@@ -181,7 +181,7 @@ Worker가 실행 중인 상태에서 다른 터미널에서 실행하세요.
181
181
 
182
182
  ```python
183
183
  from DefStream.Broker.Implements.RabbitMQ import Configuration, Connection
184
- from DefStream.Worker import request, send
184
+ from DefStream.Worker import emit, request
185
185
  from tasks import Add
186
186
 
187
187
 
@@ -193,7 +193,7 @@ connection = Connection(Configuration(
193
193
  ))
194
194
  try:
195
195
  connection.connect()
196
- message_id = send(
196
+ message_id = emit(
197
197
  {'a': 10, 'b': 20},
198
198
  task=Add,
199
199
  broker=connection,
@@ -214,7 +214,7 @@ finally:
214
214
  python client.py
215
215
  ```
216
216
 
217
- `send()`와 `request()`는 **각각 별도의 작업을 발행**합니다. 위 예제는 덧셈을 두 번 실행하며,
217
+ `emit()`와 `request()`는 **각각 별도의 작업을 발행**합니다. 위 예제는 덧셈을 두 번 실행하며,
218
218
  `request()`의 결과는 `30`입니다. `request()`의 제한 시간은 초 단위이고,
219
219
  시간이 초과되어도 이미 전달된 작업은 취소되지 않습니다.
220
220
 
@@ -225,14 +225,20 @@ python client.py
225
225
  | 함수 | 역할 | 연결 관리 |
226
226
  | --- | --- | --- |
227
227
  | `declare(task=..., broker=...)` | 작업의 큐·구독 리소스 선언 | 호출자가 연결·종료 |
228
- | `send(body, task=..., broker=...)` | 작업 목적지로 단방향 메시지 발행 | 호출자가 연결·종료 |
228
+ | `emit(body, task=..., broker=...)` | 작업 목적지로 단방향 메시지 발행 | 호출자가 연결·종료 |
229
229
  | `request(body, task=..., broker=..., timeout=5)` | 작업 결과를 동기 RPC로 요청 | 호출자가 연결·종료; RabbitMQ만 지원 |
230
230
 
231
231
  세 함수는 `DefStream.Worker`에서 가져옵니다. 전달된 연결을 자동으로 열거나 닫지 않으며,
232
- `send()`와 `request()`는 목적지를 자동 선언하지 않습니다.
232
+ `emit()`와 `request()`는 목적지를 자동 선언하지 않습니다.
233
233
  수신 Worker 또는 별도의 준비 단계에서 먼저 `declare()`를 호출하세요.
234
234
  하나의 연결을 같은 소유 스레드에서 여러 발행에 재사용할 수 있습니다.
235
235
 
236
+ 세 함수 모두 공통 `Connection`을 받고, 내부에서 선언·발행·RPC 지원 여부를 확인합니다.
237
+ 지원하지 않는 기능은 `NotImplementedError`로 실패합니다.
238
+ 기존 작업 발행 함수와 연결의 `send`는 `emit`으로 이름이 바뀌었습니다.
239
+ 사용자 정의 브로커의 작업 발행 계약도 `TaskSender.send` 대신 `Emittable.emit`을 사용하세요.
240
+ 큐·Exchange·Stream의 저수준 `Sendable.send()`와 RPC `Callable.call()`은 그대로입니다.
241
+
236
242
  작업 본문은 **문자열 키를 가진 매핑**이어야 하며, 반환값은 어댑터가 직렬화할 수 있어야 합니다.
237
243
  하나의 Worker에서는 같은 큐에 여러 작업을 중복 등록할 수 없습니다.
238
244
  메시지 유형을 보고 여러 `Run` 중 하나를 고르는 방식이 아니라 큐별로 작업을 선택합니다.
@@ -250,7 +256,7 @@ from DefStream.Worker import (
250
256
  Run,
251
257
  declare,
252
258
  request,
253
- send,
259
+ emit,
254
260
  )
255
261
 
256
262
 
@@ -275,7 +281,7 @@ declare(
275
281
  task=Add,
276
282
  broker=broker,
277
283
  )
278
- send(
284
+ emit(
279
285
  {'a': 10, 'b': 20},
280
286
  task=Add,
281
287
  broker=broker,
@@ -315,6 +321,10 @@ result = request(
315
321
  브로커 리소스를 직접 사용할 때의 공통 메서드는 다음과 같습니다.
316
322
  모든 리소스가 모든 메서드를 지원하는 것은 아닙니다.
317
323
 
324
+ 연결의 `exchange()`·`queue()`·`stream()`·`consumer()` 지원 여부는 각각
325
+ `GetExchange`·`GetQueue`·`GetStream`·`GetConsumer`로 `isinstance` 또는 `issubclass`
326
+ 검사할 수 있습니다. 이 계약들은 `DefStream.Broker`에서 가져옵니다.
327
+
318
328
  | 메서드 | 의미 | 제한 시간 단위 |
319
329
  | --- | --- | --- |
320
330
  | `send(body)` | 메시지 발행 | 어댑터별 설정 |
@@ -579,6 +589,11 @@ inspector = Inspector(
579
589
  Inspector 자체는 TLS를 제공하지 않으며 공개 웹 서버가 아닙니다.
580
590
  콘솔의 연결 팩터리는 호출마다 새 연결을 반환해야 하고 Worker 연결을 공유하면 안 됩니다.
581
591
 
592
+ Console의 `broker` 인자는 `DefStream.Broker.BrokerFactory` 계약을 사용합니다.
593
+ 이 계약의 `__call__() -> Connection`은 인자 없이 새 연결을 반환합니다.
594
+ 위의 `create_connection` 같은 함수나 람다도 그대로 전달할 수 있으며,
595
+ 클래스로 구현할 때는 `BrokerFactory`를 상속하고 `__call__`을 구현할 수 있습니다.
596
+
582
597
  ## 브로커 선택과 운영 주의사항
583
598
 
584
599
  | 기능 | RabbitMQ | Redis Streams |
@@ -151,7 +151,7 @@ Run this in another terminal while the Worker is running.
151
151
 
152
152
  ```python
153
153
  from DefStream.Broker.Implements.RabbitMQ import Configuration, Connection
154
- from DefStream.Worker import request, send
154
+ from DefStream.Worker import emit, request
155
155
  from tasks import Add
156
156
 
157
157
 
@@ -163,7 +163,7 @@ connection = Connection(Configuration(
163
163
  ))
164
164
  try:
165
165
  connection.connect()
166
- message_id = send(
166
+ message_id = emit(
167
167
  {'a': 10, 'b': 20},
168
168
  task=Add,
169
169
  broker=connection,
@@ -184,7 +184,7 @@ finally:
184
184
  python client.py
185
185
  ```
186
186
 
187
- `send()` and `request()` **each publish a separate task**. This example performs
187
+ `emit()` and `request()` **each publish a separate task**. This example performs
188
188
  the addition twice; `request()` returns `30`. The request timeout is in seconds
189
189
  and does not cancel work that has already been delivered.
190
190
 
@@ -195,14 +195,21 @@ and does not cancel work that has already been delivered.
195
195
  | Function | Purpose | Connection ownership |
196
196
  | --- | --- | --- |
197
197
  | `declare(task=..., broker=...)` | Declare task queues and subscription resources | Caller connects and closes |
198
- | `send(body, task=..., broker=...)` | Publish a one-way message to a task | Caller connects and closes |
198
+ | `emit(body, task=..., broker=...)` | Publish a one-way message to a task | Caller connects and closes |
199
199
  | `request(body, task=..., broker=..., timeout=5)` | Request a task result synchronously | Caller connects and closes; RabbitMQ only |
200
200
 
201
201
  Import these functions from `DefStream.Worker`. They do not connect or close
202
- the supplied connection. Neither `send()` nor `request()` declares destinations.
202
+ the supplied connection. Neither `emit()` nor `request()` declares destinations.
203
203
  Call `declare()` in the receiving Worker's setup or a separate provisioning step.
204
204
  Reuse a connection for multiple publications on its owning thread.
205
205
 
206
+ All three helpers accept the common `Connection` type and check declaration,
207
+ emission, or RPC support internally. Unsupported operations raise `NotImplementedError`.
208
+ The task helper and connection method previously named `send` are now named `emit`.
209
+ Custom brokers should use `Emittable.emit` instead of `TaskSender.send` for task emission.
210
+ Low-level `Sendable.send()` and RPC `Callable.call()` on queues, exchanges, and streams
211
+ remain unchanged.
212
+
206
213
  Task bodies must be **mappings with string keys**. Return values must be
207
214
  serializable by the adapter. A Worker cannot register multiple tasks for the
208
215
  same queue: routing selects tasks by queue, not by a type field in the message.
@@ -220,7 +227,7 @@ from DefStream.Worker import (
220
227
  Run,
221
228
  declare,
222
229
  request,
223
- send,
230
+ emit,
224
231
  )
225
232
 
226
233
 
@@ -245,7 +252,7 @@ declare(
245
252
  task=Add,
246
253
  broker=broker,
247
254
  )
248
- send(
255
+ emit(
249
256
  {'a': 10, 'b': 20},
250
257
  task=Add,
251
258
  broker=broker,
@@ -287,6 +294,10 @@ result = request(
287
294
  The common resource operations below apply when accessing a broker directly.
288
295
  Not every resource supports every operation.
289
296
 
297
+ Use `isinstance` or `issubclass` with `GetExchange`, `GetQueue`, `GetStream`,
298
+ or `GetConsumer` to check whether a connection provides `exchange()`, `queue()`,
299
+ `stream()`, or `consumer()`, respectively. Import these contracts from `DefStream.Broker`.
300
+
290
301
  | Method | Purpose | Timeout unit |
291
302
  | --- | --- | --- |
292
303
  | `send(body)` | Publish a message | Adapter configuration |
@@ -561,6 +572,11 @@ Inspector has no built-in TLS and is not a public web server.
561
572
  The console's connection factory must return a new connection on every call,
562
573
  never the Worker's connection.
563
574
 
575
+ Console's `broker` parameter uses the `DefStream.Broker.BrokerFactory` contract.
576
+ Its `__call__() -> Connection` takes no arguments and returns a new connection.
577
+ Functions such as `create_connection` above and lambdas remain valid without changes.
578
+ For a class-based factory, you can inherit `BrokerFactory` and implement `__call__`.
579
+
564
580
  ## Broker selection and operational considerations
565
581
 
566
582
  | Feature | RabbitMQ | Redis Streams |
@@ -148,7 +148,7 @@ Worker가 실행 중인 상태에서 다른 터미널에서 실행하세요.
148
148
 
149
149
  ```python
150
150
  from DefStream.Broker.Implements.RabbitMQ import Configuration, Connection
151
- from DefStream.Worker import request, send
151
+ from DefStream.Worker import emit, request
152
152
  from tasks import Add
153
153
 
154
154
 
@@ -160,7 +160,7 @@ connection = Connection(Configuration(
160
160
  ))
161
161
  try:
162
162
  connection.connect()
163
- message_id = send(
163
+ message_id = emit(
164
164
  {'a': 10, 'b': 20},
165
165
  task=Add,
166
166
  broker=connection,
@@ -181,7 +181,7 @@ finally:
181
181
  python client.py
182
182
  ```
183
183
 
184
- `send()`와 `request()`는 **각각 별도의 작업을 발행**합니다. 위 예제는 덧셈을 두 번 실행하며,
184
+ `emit()`와 `request()`는 **각각 별도의 작업을 발행**합니다. 위 예제는 덧셈을 두 번 실행하며,
185
185
  `request()`의 결과는 `30`입니다. `request()`의 제한 시간은 초 단위이고,
186
186
  시간이 초과되어도 이미 전달된 작업은 취소되지 않습니다.
187
187
 
@@ -192,14 +192,20 @@ python client.py
192
192
  | 함수 | 역할 | 연결 관리 |
193
193
  | --- | --- | --- |
194
194
  | `declare(task=..., broker=...)` | 작업의 큐·구독 리소스 선언 | 호출자가 연결·종료 |
195
- | `send(body, task=..., broker=...)` | 작업 목적지로 단방향 메시지 발행 | 호출자가 연결·종료 |
195
+ | `emit(body, task=..., broker=...)` | 작업 목적지로 단방향 메시지 발행 | 호출자가 연결·종료 |
196
196
  | `request(body, task=..., broker=..., timeout=5)` | 작업 결과를 동기 RPC로 요청 | 호출자가 연결·종료; RabbitMQ만 지원 |
197
197
 
198
198
  세 함수는 `DefStream.Worker`에서 가져옵니다. 전달된 연결을 자동으로 열거나 닫지 않으며,
199
- `send()`와 `request()`는 목적지를 자동 선언하지 않습니다.
199
+ `emit()`와 `request()`는 목적지를 자동 선언하지 않습니다.
200
200
  수신 Worker 또는 별도의 준비 단계에서 먼저 `declare()`를 호출하세요.
201
201
  하나의 연결을 같은 소유 스레드에서 여러 발행에 재사용할 수 있습니다.
202
202
 
203
+ 세 함수 모두 공통 `Connection`을 받고, 내부에서 선언·발행·RPC 지원 여부를 확인합니다.
204
+ 지원하지 않는 기능은 `NotImplementedError`로 실패합니다.
205
+ 기존 작업 발행 함수와 연결의 `send`는 `emit`으로 이름이 바뀌었습니다.
206
+ 사용자 정의 브로커의 작업 발행 계약도 `TaskSender.send` 대신 `Emittable.emit`을 사용하세요.
207
+ 큐·Exchange·Stream의 저수준 `Sendable.send()`와 RPC `Callable.call()`은 그대로입니다.
208
+
203
209
  작업 본문은 **문자열 키를 가진 매핑**이어야 하며, 반환값은 어댑터가 직렬화할 수 있어야 합니다.
204
210
  하나의 Worker에서는 같은 큐에 여러 작업을 중복 등록할 수 없습니다.
205
211
  메시지 유형을 보고 여러 `Run` 중 하나를 고르는 방식이 아니라 큐별로 작업을 선택합니다.
@@ -217,7 +223,7 @@ from DefStream.Worker import (
217
223
  Run,
218
224
  declare,
219
225
  request,
220
- send,
226
+ emit,
221
227
  )
222
228
 
223
229
 
@@ -242,7 +248,7 @@ declare(
242
248
  task=Add,
243
249
  broker=broker,
244
250
  )
245
- send(
251
+ emit(
246
252
  {'a': 10, 'b': 20},
247
253
  task=Add,
248
254
  broker=broker,
@@ -282,6 +288,10 @@ result = request(
282
288
  브로커 리소스를 직접 사용할 때의 공통 메서드는 다음과 같습니다.
283
289
  모든 리소스가 모든 메서드를 지원하는 것은 아닙니다.
284
290
 
291
+ 연결의 `exchange()`·`queue()`·`stream()`·`consumer()` 지원 여부는 각각
292
+ `GetExchange`·`GetQueue`·`GetStream`·`GetConsumer`로 `isinstance` 또는 `issubclass`
293
+ 검사할 수 있습니다. 이 계약들은 `DefStream.Broker`에서 가져옵니다.
294
+
285
295
  | 메서드 | 의미 | 제한 시간 단위 |
286
296
  | --- | --- | --- |
287
297
  | `send(body)` | 메시지 발행 | 어댑터별 설정 |
@@ -546,6 +556,11 @@ inspector = Inspector(
546
556
  Inspector 자체는 TLS를 제공하지 않으며 공개 웹 서버가 아닙니다.
547
557
  콘솔의 연결 팩터리는 호출마다 새 연결을 반환해야 하고 Worker 연결을 공유하면 안 됩니다.
548
558
 
559
+ Console의 `broker` 인자는 `DefStream.Broker.BrokerFactory` 계약을 사용합니다.
560
+ 이 계약의 `__call__() -> Connection`은 인자 없이 새 연결을 반환합니다.
561
+ 위의 `create_connection` 같은 함수나 람다도 그대로 전달할 수 있으며,
562
+ 클래스로 구현할 때는 `BrokerFactory`를 상속하고 `__call__`을 구현할 수 있습니다.
563
+
549
564
  ## 브로커 선택과 운영 주의사항
550
565
 
551
566
  | 기능 | RabbitMQ | Redis Streams |
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## 변경 후 (TO-BE)
9
9
 
10
- 지원 브로커의 작업 구독 설정에 기본·최대 우선순위를 정의하고, `send`와 `request`에서
10
+ 지원 브로커의 작업 구독 설정에 기본·최대 우선순위를 정의하고, `emit`과 `request`에서
11
11
  메시지별 우선순위를 재정의할 수 있습니다. 현재 지원 브로커는 RabbitMQ입니다.
12
12
 
13
13
  ## 사용 방법
@@ -20,7 +20,7 @@ RabbitMQ 작업의 `parameters`에 `Subscription(priority=2, max_priority=5, ...
20
20
  from DefStream.Worker import (
21
21
  declare,
22
22
  request,
23
- send,
23
+ emit,
24
24
  )
25
25
 
26
26
 
@@ -31,7 +31,7 @@ declare(
31
31
  )
32
32
 
33
33
  # 호출값을 생략하면 작업 구독의 기본 우선순위를 사용합니다.
34
- send(
34
+ emit(
35
35
  {'a': 1, 'b': 2},
36
36
  task=Add,
37
37
  broker=broker,
@@ -131,3 +131,102 @@ RabbitMQ 선택적 통합 테스트는 활성화되어 실제 서버에 접속
131
131
  `WorkerConnection`을 직접 import하거나 타입 힌트에 쓰던 코드는
132
132
  `from DefStream.Broker import Connection`으로 변경해야 한다.
133
133
  컨슈머 없는 연결은 워커 생성 시점이 아니라 실행 중 컨슈머 생성 직전에 거부된다.
134
+
135
+ ## 7. 기능별 연결 검사와 작업 발행 이름 통일
136
+
137
+ 추가 요구사항에 따라 다음을 반영했다.
138
+
139
+ - `GetExchange`, `GetQueue`, `GetStream`에 `@runtime_checkable`을 추가했다.
140
+ - `TaskSender`를 `Emittable`로, `send` 작업 도우미와 브로커 메서드를 `emit`으로
141
+ 변경했다. 공개 export·우선순위 계약·RabbitMQ·Redis 어댑터도 함께 변경했다.
142
+ 기존 이름의 호환 별칭은 제공하지 않는다.
143
+ - `declare`, `emit`, `request`의 입력을 모두 `broker: Connection`으로 통일했다.
144
+ 내부에서 각각 `Declarable`, `Emittable`, `Requestable`을 검사한다.
145
+ - `request`의 잘못된 `TaskSender` 타입을 제거하고 RPC만 가능한 연결도 지원한다.
146
+ RPC 지원 검사는 우선순위 처리 전에 수행한다.
147
+ - `PrioritySupport`는 이미 제공하던 발행·RPC 계약을 상속 관계로도 표현하도록
148
+ `Emittable`, `Requestable`을 상속한다. 선택적 `priority` 인자를 정적 분석에서도
149
+ 올바르게 해석하게 하며, RabbitMQ는 중복 상속을 제거했다.
150
+ - Inspector Console의 별도 `Producer` 합성 타입을 제거하고 팩터리가
151
+ `Connection`을 반환하도록 변경했다. 내부 발행은 `emit`을 사용하지만
152
+ HTTP의 `mode="send"`와 기존 화면은 유지했다.
153
+ - 저수준 `Sendable.send()`·`Callable.call()`은 유지한다.
154
+ - 관련 테스트와 예제, 코어·어댑터의 한영 README 및 연결된 사용 예제를 갱신했다.
155
+
156
+ ### 추가 검증 결과
157
+
158
+ 현재 소스를 직접 로드하는 동일한 검증 방식으로 Docker `defstream-rabbitmq`를
159
+ 재시작하고 `DEFSTREAM_RABBITMQ_TESTS=1`로 실행했다.
160
+
161
+ | 대상 | 전체 | 통과 | 건너뜀 | 실패·오류 |
162
+ |---|---:|---:|---:|---:|
163
+ | 코어 | 164 | 160 | 4 | 0 |
164
+ | RabbitMQ 어댑터 | 60 | 60 | 0 | 0 |
165
+ | Redis 어댑터 | 36 | 32 | 4 | 0 |
166
+ | 합계 | 260 | 252 | 8 | 0 |
167
+
168
+ - 건너뛴 8개는 Redis 실서버 전용 테스트이다. Redis 실제 서버 테스트는 실행하지 않았다.
169
+ - 생성자와 도우미 타입, 기능별 지원·거부, RPC 전용 연결, `emit` 공개 이름과
170
+ 기존 작업 `send` 제거, 런타임 Protocol 검사를 검증했다.
171
+ - 기존 우선순위 테스트와 실제 RabbitMQ 발행·RPC·소비·실패 처리·Inspector가 통과했다.
172
+ - `Message.py`, `Broker/Connection.py`와 양쪽 공개 export는 Pylance 오류가 없었다.
173
+ Console에는 기존 미사용 매개변수 안내만 남아 있다.
174
+ - Pylance가 해석한 `emit` 호출 위치는 시그니처와 호환됐다.
175
+ 테스트 도구에서는 테스트를 찾지 못해 기존 `unittest`로 검증했다.
176
+ - 검증 후 테스트용 RabbitMQ를 종료하고 재사용 가능한 컨테이너는 보존했다.
177
+
178
+ ## 8. Redis·RabbitMQ 동시 실서버 검증
179
+
180
+ 2026-10-19에 Redis 전용 Docker 컨테이너를 추가하고, 이전에 건너뛴 Redis
181
+ 통합 테스트까지 모두 실행했다. 위의 Redis 미검증 기록은 이 재검증 이전 결과이다.
182
+
183
+ - 컨테이너: `defstream-redis`, 이미지: `redis:7`, 실제 Redis 버전: `7.4.11`.
184
+ - 포트는 `127.0.0.1:6379`에만 공개했고 `redis-cli ping`의 `PONG`을 확인했다.
185
+ - `defstream-rabbitmq`도 다시 시작하고 `rabbitmq-diagnostics -q ping`을 확인했다.
186
+ - `DEFSTREAM_REDIS_TESTS=1`과 `DEFSTREAM_RABBITMQ_TESTS=1`을 동시에 설정했다.
187
+ - 가상환경에 설치된 이전 패키지가 아니라 현재 코어·어댑터 소스를 직접 로드해
188
+ 각 프로젝트의 전체 `unittest`를 별도 Python 프로세스에서 실행했다.
189
+
190
+ ```powershell
191
+ docker run -d --name defstream-redis -p 127.0.0.1:6379:6379 redis:7
192
+ docker exec defstream-redis redis-cli ping
193
+ docker start defstream-rabbitmq
194
+ docker exec defstream-rabbitmq rabbitmq-diagnostics -q ping
195
+ $env:DEFSTREAM_REDIS_TESTS = '1'
196
+ $env:DEFSTREAM_RABBITMQ_TESTS = '1'
197
+ $env:PYTHONIOENCODING = 'utf-8'
198
+ $env:PYTHONUTF8 = '1'
199
+ ```
200
+
201
+ | 대상 | 전체 | 통과 | 건너뜀 | 실패·오류 | 소요 시간 |
202
+ |---|---:|---:|---:|---:|---:|
203
+ | 코어 | 164 | 164 | 0 | 0 | 32.319초 |
204
+ | RabbitMQ 어댑터 | 60 | 60 | 0 | 0 | 5.546초 |
205
+ | Redis 어댑터 | 36 | 36 | 0 | 0 | 2.198초 |
206
+ | 합계 | 260 | 260 | 0 | 0 | 40.063초 |
207
+
208
+ Redis의 발행·소비·이력 읽기·원자적 재전달, QoS·콜백·정상 종료, 방치된 pending
209
+ 회수와 실행 풀 연동을 검증했다. 코어의 Redis 발행·완료 훅·Inspector 상태·메트릭·Console
210
+ 통합 테스트도 통과했다. RabbitMQ 통합 테스트 역시 활성화된 상태로 통과했다.
211
+
212
+ 검증 후 Redis `DBSIZE`가 `0`임을 확인했다. 두 컨테이너 모두 종료했고
213
+ `exited`, `running=false` 상태를 확인했다. 컨테이너는 보존하여
214
+ `docker start defstream-redis defstream-rabbitmq`로 재사용할 수 있다.
215
+
216
+ ## 9. 브로커 팩터리 계약 명명
217
+
218
+ - `Broker/Connection.py`에 `BrokerFactory` Protocol을 정의하고
219
+ `DefStream.Broker`에서 공개했다.
220
+ - `__call__(self) -> Connection`으로 인자 없는 새 연결 생성 계약을 명시했다.
221
+ 독립적인 연결을 매번 반환해야 한다는 책임을 독스트링에 기록했다.
222
+ - Console의 `broker` 타입을 `Callable[[], Connection]`에서 `BrokerFactory`로
223
+ 변경했다. 기존 `callable` 검사와 연결 생성·종료 흐름은 변경하지 않았다.
224
+ - 함수·람다·명시적 상속 클래스·구조적 호출 클래스 모두 사용할 수 있도록 유지했다.
225
+ - 타입 힌트, 공개 export, 불완전한 구현의 인스턴스화 거부, 네 가지 팩터리 형태와
226
+ 호출마다 서로 다른 연결을 반환하는 동작을 테스트했다.
227
+ - 한영 README와 사용자용 변경 로그에 계약과 기존 코드 호환성을 설명했다.
228
+ - 현재 소스를 직접 로드해 계약·Console 테스트 31개 중 29개 통과,
229
+ 실서버 전용 2개 건너뜀을 확인했다. 이번 타입 명명 변경에서는 Docker 실서버
230
+ 테스트를 재실행하지 않았으며, 이전 260개 실서버 검증과 구분한다.
231
+ - `Broker/Connection.py`의 Pylance 진단에 오류가 없었다.
232
+ Console에는 기존 미사용 매개변수 안내만 남아 있다.
@@ -0,0 +1,94 @@
1
+ # 워커에 공통 브로커 연결 타입 사용
2
+
3
+ ## 달라진 점
4
+
5
+ 이전에는 워커에 전달할 연결의 타입을 표시하려면 워커 전용 `WorkerConnection`을
6
+ 사용해야 했습니다. 이제 `DefStream.Broker.Connection`을 사용하면 됩니다.
7
+ 워커를 위해 별도의 연결 타입을 가져오거나 정의할 필요가 없습니다.
8
+
9
+ RabbitMQ·Redis 연결 객체를 `Worker`에 전달하는 기존 코드는 그대로 사용할 수 있습니다.
10
+ 메시지 처리, ACK/NACK, 실패 정책, RPC와 스레드·프로세스 풀의 동작도 동일합니다.
11
+
12
+ ## 기존 코드에서 바꿀 부분
13
+
14
+ `WorkerConnection`을 직접 가져오거나 타입 힌트에 사용했다면 공통 `Connection`으로
15
+ 변경하세요. `WorkerConnection`은 더 이상 제공하지 않습니다.
16
+
17
+ 변경 전:
18
+
19
+ ```python
20
+ from DefStream.Worker import WorkerConnection
21
+ ```
22
+
23
+ 변경 후:
24
+
25
+ ```python
26
+ from DefStream.Broker import Connection
27
+ ```
28
+
29
+ 해당 타입을 사용한 매개변수·반환값·변수의 타입 힌트도 `Connection`으로 바꾸면 됩니다.
30
+ 브로커 객체만 전달하고 있었다면 수정할 필요가 없습니다.
31
+
32
+ ## 직접 만든 브로커를 사용하는 경우
33
+
34
+ 워커에서 사용할 연결에는 `connect()`, `close()` 외에 컨슈머를 만드는 `consumer()`가
35
+ 있어야 합니다. 호출자가 별도로 검사하거나 워커 전용 타입을 상속할 필요는 없습니다.
36
+
37
+ 워커가 연결과 setup을 마친 뒤 `consumer()` 지원 여부를 확인합니다.
38
+ 지원하지 않으면 `TypeError: Worker broker must support consumer creation`으로
39
+ 실패하고 종료 처리를 수행합니다. 메시지 발행만 가능한 연결은 워커에 사용할 수 없습니다.
40
+
41
+ 공통 `Connection` 자체에는 `consumer()` 구현을 강제하지 않으므로,
42
+ 워커에 사용하지 않는 발행 전용 연결은 변경할 필요가 없습니다.
43
+
44
+ ## 작업 발행은 `emit` 사용
45
+
46
+ 작업을 보내는 함수와 브로커 연결 메서드의 이름이 `send`에서 `emit`으로 바뀌었습니다.
47
+ 코어와 RabbitMQ·Redis 어댑터를 함께 갱신하세요. 이전 이름은 더 이상 제공하지 않습니다.
48
+
49
+ ```python
50
+ from DefStream.Worker import emit
51
+
52
+
53
+ # broker는 호출자가 연결한 브로커이며, Add는 기존 작업 클래스입니다.
54
+ emit(
55
+ {'a': 10, 'b': 20},
56
+ task=Add,
57
+ broker=broker,
58
+ )
59
+ ```
60
+
61
+ 직접 `connection.send(body, parameters)`를 호출했다면
62
+ `connection.emit(body, parameters)`로 바꾸세요.
63
+ 큐·Exchange·Stream을 직접 사용하는 `send(body)`와 RPC `call(body)`는 바뀌지 않습니다.
64
+
65
+ `declare`, `emit`, `request` 모두 공통 `Connection`을 받습니다.
66
+ 사용하는 쪽에서 기능별 연결 타입을 따로 지정할 필요가 없으며,
67
+ 지원하지 않는 기능을 호출하면 `NotImplementedError`가 발생합니다.
68
+ 이 함수들은 여전히 연결을 자동으로 열거나 닫지 않습니다.
69
+
70
+ 사용자 정의 브로커에서 `TaskSender`를 사용했다면 `DefStream.Broker.Emittable`을
71
+ 가져오고 작업 발행 메서드 이름을 `emit`으로 변경하세요.
72
+ 선언과 RPC의 계약인 `Declarable.declare`와 `Requestable.request`는 유지됩니다.
73
+
74
+ ## 연결 기능 지원 여부 확인
75
+
76
+ `GetExchange`, `GetQueue`, `GetStream`도 `GetConsumer`처럼 런타임 검사를 지원합니다.
77
+ 예를 들어 `isinstance(connection, GetQueue)` 또는
78
+ `issubclass(ConnectionClass, GetQueue)`로 큐 생성 기능의 지원 여부를 확인할 수 있습니다.
79
+ 각 계약은 `DefStream.Broker`에서 가져옵니다.
80
+
81
+ ## 브로커 연결 팩터리 타입
82
+
83
+ Console에 전달하는 연결 생성 함수의 타입을 `BrokerFactory`라는 이름으로 제공합니다.
84
+ `from DefStream.Broker import BrokerFactory`로 가져올 수 있으며,
85
+ 인자 없는 `__call__()`이 새 `Connection`을 반환하는 계약입니다.
86
+
87
+ 기존 함수나 람다를 전달하는 코드는 바꾸지 않아도 됩니다.
88
+ 클래스로 팩터리를 구현하려면 `BrokerFactory`를 상속하고 `__call__()`을 구현할 수 있습니다.
89
+ 호출마다 새 연결을 반환해야 하며 Worker의 연결을 재사용하면 안 됩니다.
90
+
91
+ ## 상세 기록
92
+
93
+ - [요구사항 명세서](./REQUIREMENTS.md)
94
+ - [구현 및 RabbitMQ 검증 기록](./IMPLEMENTS.md)
@@ -34,7 +34,7 @@
34
34
  ## 4. 범위와 제한
35
35
 
36
36
  - 변경 대상은 코어의 연결 계약, 워커, 직접 관련된 테스트와 문서이다.
37
- - RabbitMQ·Redis 어댑터의 공개 API나 구현은 변경하지 않는다.
37
+ - RabbitMQ·Redis 어댑터는 아래 추가 요구사항에 따라 작업 발행 이름을 함께 변경한다.
38
38
  - 사용자 정의 연결에 `GetConsumer`의 명시적 상속을 강제하지 않는다.
39
39
  - 런타임 Protocol 검사는 기능의 구조적 지원 여부를 확인한다.
40
40
  메서드 매개변수·반환 타입이나 실제 실행 성공까지 검증하는 기능은 아니다.
@@ -50,3 +50,29 @@
50
50
  | WCAT-04 | 기존 워커 수명 주기, setup·cleanup, 스레드·프로세스 실행 테스트가 통과한다. |
51
51
  | WCAT-05 | Docker의 `defstream-rabbitmq`를 사용하여 실제 소비·재전달·거부·종료, RPC, Inspector 연동을 검증한다. RabbitMQ 테스트를 건너뛴 결과를 실서버 검증으로 간주하지 않는다. |
52
52
  | WCAT-06 | 설치된 과거 패키지가 아니라 현재 브랜치의 코어 소스와 로컬 RabbitMQ 어댑터를 로드해 검증한다. |
53
+
54
+ ## 6. 연결 기능 검사와 작업 발행 이름 추가 요구사항
55
+
56
+ - `GetExchange`, `GetQueue`, `GetStream`에도 `@runtime_checkable`을 적용한다.
57
+ - `TaskSender`는 `Emittable`로, 작업 발행 메서드와 워커 도우미 `send`는
58
+ `emit`으로 변경한다. 기존 이름의 호환 별칭은 추가하지 않는다.
59
+ - `declare`, `emit`, `request`는 모두 `broker: Connection`을 받고 내부에서
60
+ 각각 `Declarable`, `Emittable`, `Requestable`을 검사한다.
61
+ - 미지원 기능은 기존 방식의 `NotImplementedError`로 명시적으로 실패한다.
62
+ RPC 검사는 우선순위 유무와 무관하게 수행한다.
63
+ - 우선순위 기능 계약과 RabbitMQ·Redis 구현체의 작업 발행 이름도 `emit`으로 맞춘다.
64
+ - 큐·Exchange·Stream의 저수준 `Sendable.send()`와 `Callable.call()`은 유지한다.
65
+ - Inspector Console의 브로커 팩터리도 공통 `Connection`을 반환하도록 단순화한다.
66
+ 기존 HTTP `mode="send"`와 화면 동작은 유지하고 내부 호출만 `emit`으로 바꾼다.
67
+ - 테스트, 예제, 한영 사용 설명서 및 각 프로젝트 현재 브랜치 문서를 갱신한다.
68
+ - 생성자와 도우미 타입 힌트, 기능별 성공·실패, 우선순위, 실제 RabbitMQ 연동과
69
+ Redis 회귀 테스트로 검증한다.
70
+
71
+ ## 7. 브로커 팩터리 계약
72
+
73
+ - 공통 브로커에 `BrokerFactory` Protocol을 공개하며 `__call__(self) -> Connection`을 정의한다.
74
+ - Console의 `broker` 입력 타입은 `Callable[[], Connection]` 대신 `BrokerFactory`를 사용한다.
75
+ - 기존 함수·람다와 호출 가능한 클래스도 구조적으로 사용할 수 있어야 한다.
76
+ 명시적 상속이나 어댑터를 호출자에게 강제하지 않는다.
77
+ - 호출마다 독립적인 새 연결을 반환하는 계약을 문서화한다.
78
+ Console의 기존 호출 가능 여부 검사와 연결 생성·종료 동작은 유지한다.
@@ -0,0 +1,4 @@
1
+ {
2
+ "DefStream-RabbitMQ": "fix/3",
3
+ "DefStream-Redis": "fix/3"
4
+ }