DefStream 0.1.12__tar.gz → 0.1.13__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 (117) hide show
  1. defstream-0.1.13/.github/ISSUE_TEMPLATE/bug_report.yml +61 -0
  2. defstream-0.1.13/.github/ISSUE_TEMPLATE/config.yml +1 -0
  3. defstream-0.1.13/.github/ISSUE_TEMPLATE/feature_request.yml +36 -0
  4. defstream-0.1.13/.github/PULL_REQUEST_TEMPLATE/hotfix.md +34 -0
  5. defstream-0.1.13/.github/PULL_REQUEST_TEMPLATE.md +24 -0
  6. {defstream-0.1.12 → defstream-0.1.13}/.gitignore +2 -4
  7. {defstream-0.1.12 → defstream-0.1.13}/DefStream.egg-info/PKG-INFO +1 -1
  8. {defstream-0.1.12 → defstream-0.1.13}/DefStream.egg-info/SOURCES.txt +9 -0
  9. {defstream-0.1.12 → defstream-0.1.13}/PKG-INFO +1 -1
  10. defstream-0.1.13/issues/bug/16/IMPLEMENTS.md +32 -0
  11. defstream-0.1.13/issues/bug/16/ISSUE.md +19 -0
  12. defstream-0.1.13/issues/bug/16/README.md +12 -0
  13. defstream-0.1.13/issues/bug/16/REQUIREMENTS.md +25 -0
  14. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/Console.py +4 -3
  15. {defstream-0.1.12 → defstream-0.1.13}/test/test_inspector_console.py +56 -2
  16. {defstream-0.1.12 → defstream-0.1.13}/.github/workflows/ci.yml +0 -0
  17. {defstream-0.1.12 → defstream-0.1.13}/DefStream.egg-info/dependency_links.txt +0 -0
  18. {defstream-0.1.12 → defstream-0.1.13}/DefStream.egg-info/requires.txt +0 -0
  19. {defstream-0.1.12 → defstream-0.1.13}/DefStream.egg-info/top_level.txt +0 -0
  20. {defstream-0.1.12 → defstream-0.1.13}/LICENSE +0 -0
  21. {defstream-0.1.12 → defstream-0.1.13}/README.en.md +0 -0
  22. {defstream-0.1.12 → defstream-0.1.13}/README.md +0 -0
  23. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/1/IMPLEMENTS.md +0 -0
  24. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/1/README.md +0 -0
  25. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/1/REQUIREMENTS.md +0 -0
  26. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/1/TASK.md +0 -0
  27. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/1/ci.refs.json +0 -0
  28. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/8/IMPLEMENTS.md +0 -0
  29. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/8/README.md +0 -0
  30. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/8/REQUIREMENTS.md +0 -0
  31. {defstream-0.1.12 → defstream-0.1.13}/issues/feature/8/ci.refs.json +0 -0
  32. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/10/IMPLEMENTS.md +0 -0
  33. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/10/README.md +0 -0
  34. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/10/REQUIREMENTS.md +0 -0
  35. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/13/README.md +0 -0
  36. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/3/IMPLEMENTS.md +0 -0
  37. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/3/README.md +0 -0
  38. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/3/REQUIREMENTS.md +0 -0
  39. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/3/ci.refs.json +0 -0
  40. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/6/IMPLEMENTS.md +0 -0
  41. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/6/README.md +0 -0
  42. {defstream-0.1.12 → defstream-0.1.13}/issues/fix/6/REQUIREMENTS.md +0 -0
  43. {defstream-0.1.12 → defstream-0.1.13}/sample/Broker/Sample.py +0 -0
  44. {defstream-0.1.12 → defstream-0.1.13}/sample/Worker/RabbitMQ/Client.py +0 -0
  45. {defstream-0.1.12 → defstream-0.1.13}/sample/Worker/RabbitMQ/Tasks.py +0 -0
  46. {defstream-0.1.12 → defstream-0.1.13}/sample/Worker/RabbitMQ/Worker.py +0 -0
  47. {defstream-0.1.12 → defstream-0.1.13}/sample/Worker/Redis/Sample.py +0 -0
  48. {defstream-0.1.12 → defstream-0.1.13}/sample/Worker/Sample.py +0 -0
  49. {defstream-0.1.12 → defstream-0.1.13}/setup.cfg +0 -0
  50. {defstream-0.1.12 → defstream-0.1.13}/setup.py +0 -0
  51. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Configuration.py +0 -0
  52. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Connection.py +0 -0
  53. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Consumer.py +0 -0
  54. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Errors.py +0 -0
  55. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Event.py +0 -0
  56. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Implements/__init__.py +0 -0
  57. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Policies.py +0 -0
  58. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Priority.py +0 -0
  59. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/Protocol.py +0 -0
  60. {defstream-0.1.12 → defstream-0.1.13}/src/Broker/__init__.py +0 -0
  61. {defstream-0.1.12 → defstream-0.1.13}/src/Descriptor/DataObject.py +0 -0
  62. {defstream-0.1.12 → defstream-0.1.13}/src/Descriptor/Types.py +0 -0
  63. {defstream-0.1.12 → defstream-0.1.13}/src/Descriptor/Value.py +0 -0
  64. {defstream-0.1.12 → defstream-0.1.13}/src/Descriptor/__init__.py +0 -0
  65. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extension.py +0 -0
  66. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/Console.html +0 -0
  67. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/Dashboard.html +0 -0
  68. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/Dashboard.py +0 -0
  69. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/HealthCheck.py +0 -0
  70. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/Metrics.py +0 -0
  71. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/Specifications.py +0 -0
  72. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Extensions/__init__.py +0 -0
  73. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Inspector.py +0 -0
  74. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/Response.py +0 -0
  75. {defstream-0.1.12 → defstream-0.1.13}/src/Inspector/__init__.py +0 -0
  76. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Pattern.py +0 -0
  77. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Array.py +0 -0
  78. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Common.py +0 -0
  79. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Compare.py +0 -0
  80. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Condition.py +0 -0
  81. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/DataObject.py +0 -0
  82. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/DateTime.py +0 -0
  83. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Number.py +0 -0
  84. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Object.py +0 -0
  85. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Size.py +0 -0
  86. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/String.py +0 -0
  87. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/Type.py +0 -0
  88. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Patterns/__init__.py +0 -0
  89. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Validate.py +0 -0
  90. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/Validator.py +0 -0
  91. {defstream-0.1.12 → defstream-0.1.13}/src/Validator/__init__.py +0 -0
  92. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Executor.py +0 -0
  93. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Message.py +0 -0
  94. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Pool.py +0 -0
  95. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Run.py +0 -0
  96. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Specification.py +0 -0
  97. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Startup.py +0 -0
  98. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/Worker.py +0 -0
  99. {defstream-0.1.12 → defstream-0.1.13}/src/Worker/__init__.py +0 -0
  100. {defstream-0.1.12 → defstream-0.1.13}/src/__init__.py +0 -0
  101. {defstream-0.1.12 → defstream-0.1.13}/test/test_dashboard.py +0 -0
  102. {defstream-0.1.12 → defstream-0.1.13}/test/test_dashboard_ui.cjs +0 -0
  103. {defstream-0.1.12 → defstream-0.1.13}/test/test_descriptor.py +0 -0
  104. {defstream-0.1.12 → defstream-0.1.13}/test/test_inspector.py +0 -0
  105. {defstream-0.1.12 → defstream-0.1.13}/test/test_inspector_logging.py +0 -0
  106. {defstream-0.1.12 → defstream-0.1.13}/test/test_lifecycle_hooks.py +0 -0
  107. {defstream-0.1.12 → defstream-0.1.13}/test/test_logging.py +0 -0
  108. {defstream-0.1.12 → defstream-0.1.13}/test/test_pool_callbacks.py +0 -0
  109. {defstream-0.1.12 → defstream-0.1.13}/test/test_process_signals.py +0 -0
  110. {defstream-0.1.12 → defstream-0.1.13}/test/test_protocol_contracts.py +0 -0
  111. {defstream-0.1.12 → defstream-0.1.13}/test/test_release_workflow.py +0 -0
  112. {defstream-0.1.12 → defstream-0.1.13}/test/test_runner_hooks.py +0 -0
  113. {defstream-0.1.12 → defstream-0.1.13}/test/test_specifications.py +0 -0
  114. {defstream-0.1.12 → defstream-0.1.13}/test/test_task_messages.py +0 -0
  115. {defstream-0.1.12 → defstream-0.1.13}/test/test_task_priorities.py +0 -0
  116. {defstream-0.1.12 → defstream-0.1.13}/test/test_worker.py +0 -0
  117. {defstream-0.1.12 → defstream-0.1.13}/test/test_worker_startup.py +0 -0
@@ -0,0 +1,61 @@
1
+ name: 버그/오류 제보
2
+ description: 예상과 다르게 동작하거나 오류가 발생하는 문제를 제보합니다.
3
+ title: "[버그] "
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: >
8
+ 재현 가능한 버그를 제보해 주세요. 로그나 설정을 첨부할 때 토큰, 비밀번호,
9
+ 개인정보 등 민감한 정보는 반드시 삭제해 주세요.
10
+ - type: input
11
+ id: version
12
+ attributes:
13
+ label: 버전
14
+ description: 사용 중인 버전 또는 커밋을 입력해 주세요.
15
+ placeholder: 예) 0.1.12
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ id: expected
20
+ attributes:
21
+ label: 기대한 동작
22
+ description: 어떤 결과를 기대했는지 설명해 주세요.
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ id: actual
27
+ attributes:
28
+ label: 실제 동작
29
+ description: 실제로 발생한 결과를 설명해 주세요. 오류가 표시되면 메시지도 포함해 주세요.
30
+ validations:
31
+ required: true
32
+ - type: textarea
33
+ id: reproduction
34
+ attributes:
35
+ label: 재현 방법
36
+ description: 문제를 재현하는 단계나 최소 코드 예제를 작성해 주세요.
37
+ placeholder: |
38
+ 1. 다음 설정으로 Worker를 시작합니다.
39
+ 2. 특정 메시지를 전달합니다.
40
+ 3. 오류가 발생합니다.
41
+ validations:
42
+ required: true
43
+ - type: textarea
44
+ id: environment
45
+ attributes:
46
+ label: 실행 환경
47
+ description: Python 버전, 운영체제, 브로커 및 관련 어댑터 버전을 입력해 주세요.
48
+ placeholder: |
49
+ - Python:
50
+ - 운영체제:
51
+ - 브로커:
52
+ - 어댑터:
53
+ validations:
54
+ required: true
55
+ - type: textarea
56
+ id: additional
57
+ attributes:
58
+ label: 추가 정보
59
+ description: 관련 로그나 스크린샷 등 문제 파악에 도움이 되는 정보를 적어 주세요.
60
+ validations:
61
+ required: false
@@ -0,0 +1 @@
1
+ blank_issues_enabled: false
@@ -0,0 +1,36 @@
1
+ name: 기능 제안
2
+ description: DefStream에 추가하거나 개선할 기능을 제안합니다.
3
+ title: "[기능 제안] "
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: >
8
+ 해결하려는 문제와 제안하는 사용 경험을 중심으로 작성해 주세요.
9
+ - type: textarea
10
+ id: problem
11
+ attributes:
12
+ label: 해결하려는 문제
13
+ description: 현재 어떤 불편이나 제약이 있는지 설명해 주세요.
14
+ validations:
15
+ required: true
16
+ - type: textarea
17
+ id: proposal
18
+ attributes:
19
+ label: 제안하는 해결 방법
20
+ description: 원하는 기능과 기대하는 동작을 설명해 주세요.
21
+ validations:
22
+ required: true
23
+ - type: textarea
24
+ id: alternatives
25
+ attributes:
26
+ label: 고려한 대안
27
+ description: 고려한 다른 방법이나 우회 방법이 있다면 적어 주세요.
28
+ validations:
29
+ required: false
30
+ - type: textarea
31
+ id: additional
32
+ attributes:
33
+ label: 추가 정보
34
+ description: 예제, 참고 자료 등 제안의 맥락을 이해하는 데 도움이 되는 정보를 적어 주세요.
35
+ validations:
36
+ required: false
@@ -0,0 +1,34 @@
1
+ ## 핫픽스 요약
2
+
3
+ <!-- 긴급 수정이 필요한 이유와 해결 내용을 요약해 주세요. -->
4
+
5
+ ## 관련 이슈와 영향 범위
6
+
7
+ - 관련 이슈:
8
+ - 영향을 받는 버전:
9
+ - 영향받는 사용자·기능:
10
+ - 심각도 및 긴급 배포가 필요한 이유:
11
+
12
+ ## 원인과 수정 내용
13
+
14
+ <!-- 문제의 원인, 수정 방법, 변경 범위를 작성해 주세요. -->
15
+
16
+ ## 회귀 방지 및 검증
17
+
18
+ <!-- 재현 테스트와 실행한 검증 결과를 작성해 주세요. 실행하지 못한 검증은 사유를 적어 주세요. -->
19
+
20
+ - [ ] 문제를 재현하는 회귀 테스트를 추가하거나 기존 테스트로 수정 동작을 확인했습니다.
21
+ - [ ] 관련 테스트를 실행했습니다.
22
+ - [ ] 호환성 및 영향 범위를 확인했습니다.
23
+
24
+ ## 배포·복구 계획
25
+
26
+ - 배포 시 주의사항:
27
+ - 롤백 또는 복구 방법:
28
+ - 후속 수정이 필요한 경우 관련 이슈:
29
+
30
+ ## 제출 전 확인
31
+
32
+ - [ ] 수정 범위가 긴급 문제 해결에 필요한 변경으로 한정되어 있습니다.
33
+ - [ ] 오류 로그와 변경 내용을 민감 정보 없이 확인했습니다.
34
+ - [ ] 검증하지 않은 항목을 완료한 것으로 표시하지 않았습니다.
@@ -0,0 +1,24 @@
1
+ ## 변경 내용
2
+
3
+ <!-- 무엇을 왜 변경했는지 간단히 요약해 주세요. -->
4
+
5
+ ## 변경 유형
6
+
7
+ - [ ] 버그 수정
8
+ - [ ] 기능 추가
9
+ - [ ] 호환성에 영향을 주는 변경
10
+ - [ ] 문서 또는 예제 변경
11
+ - [ ] 기타
12
+
13
+ ## 검증
14
+
15
+ <!-- 실행한 테스트와 결과를 작성해 주세요. 테스트를 실행하지 않았다면 사유를 적어 주세요. -->
16
+
17
+ - [ ] 관련 테스트를 실행했습니다.
18
+ - [ ] 문서와 예제를 확인했습니다.
19
+
20
+ ## 확인 사항
21
+
22
+ - [ ] 변경 범위가 요청 사항에 한정되어 있습니다.
23
+ - [ ] 공개 API나 기존 동작에 영향을 주는 경우 변경 내용과 마이그레이션 방법을 설명했습니다.
24
+ - [ ] 민감 정보나 불필요한 디버깅 코드를 포함하지 않았습니다.
@@ -53,10 +53,8 @@ tmp/
53
53
  .git/
54
54
 
55
55
  # GitHub specific files
56
- .github/
57
- !/.github/
58
- /.github/*
59
- !/.github/workflows/
56
+ .github/instructions
57
+ .github/instructions/
60
58
 
61
59
  # GitLab specific files
62
60
  .gitlab/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DefStream
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Synchronous message processing with pluggable broker adapters
5
5
  Home-page: https://github.com/yong5eon/DefStream
6
6
  Author: Heo Yongseon
@@ -3,12 +3,21 @@ LICENSE
3
3
  README.en.md
4
4
  README.md
5
5
  setup.py
6
+ .github/PULL_REQUEST_TEMPLATE.md
7
+ .github/ISSUE_TEMPLATE/bug_report.yml
8
+ .github/ISSUE_TEMPLATE/config.yml
9
+ .github/ISSUE_TEMPLATE/feature_request.yml
10
+ .github/PULL_REQUEST_TEMPLATE/hotfix.md
6
11
  .github/workflows/ci.yml
7
12
  DefStream.egg-info/PKG-INFO
8
13
  DefStream.egg-info/SOURCES.txt
9
14
  DefStream.egg-info/dependency_links.txt
10
15
  DefStream.egg-info/requires.txt
11
16
  DefStream.egg-info/top_level.txt
17
+ issues/bug/16/IMPLEMENTS.md
18
+ issues/bug/16/ISSUE.md
19
+ issues/bug/16/README.md
20
+ issues/bug/16/REQUIREMENTS.md
12
21
  issues/feature/1/IMPLEMENTS.md
13
22
  issues/feature/1/README.md
14
23
  issues/feature/1/REQUIREMENTS.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DefStream
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Synchronous message processing with pluggable broker adapters
5
5
  Home-page: https://github.com/yong5eon/DefStream
6
6
  Author: Heo Yongseon
@@ -0,0 +1,32 @@
1
+ # Inspector Console 사용자 지정 Task 이름 버그 수정 기록
2
+
3
+ ## 구현 개요
4
+
5
+ [요구사항 명세서](./REQUIREMENTS.md)에 따라 Inspector Console이 작업 목록과
6
+ 동일한 작업 ID를 사용해 등록된 Task를 찾고, 잘못된 요청의 구체적인 원인을
7
+ 경고 로그에서 확인할 수 있도록 수정했다.
8
+
9
+ ## 주요 변경
10
+
11
+ - `Console.execute()`의 Task 검색과 중복 검사를 모두 `task.__name__`에서
12
+ `task.name` 비교로 변경했다. 작업 이름을 사용자 지정한 경우에도
13
+ Specifications 문서와 Console UI가 전달하는 ID로 올바른 Task를 식별한다.
14
+ - 잘못된 입력을 거부하는 경고 로그에 예외 종류와 예외 메시지를 함께 기록한다.
15
+ - `test_inspector_console.py`에 사용자 지정 ID의 발행 성공, 중복 ID 거부,
16
+ 미등록 ID의 오류 로그 내용을 확인하는 회귀 테스트를 추가했다.
17
+ - RabbitMQ·Redis 실서버 테스트의 요청 ID도 실제 등록된 하위 Task의 `Live.name`을
18
+ 사용하도록 했다. 클래스의 `__name__`(`Live`)와 Worker에 등록하는 유효 작업
19
+ 이름은 같다고 가정할 수 없으며, 이전의 하드코딩은 요청을 400으로 거부하게 했다.
20
+
21
+ ## 검증
22
+
23
+ DefStream 테스트 디렉터리에서 Python 3.12.10으로 다음 명령을 실행했다.
24
+
25
+ ```powershell
26
+ $env:PYTHONIOENCODING = 'utf-8'
27
+ ..\..\.venv\Scripts\python.exe -m unittest test_inspector_console test_inspector_logging
28
+ ```
29
+
30
+ Inspector Console 및 로깅 관련 테스트 28개가 통과했고, 선택 통합 테스트 2개는
31
+ 건너뛰었다. 변경된 두 Python 파일의 `compile()` 문법 검사와
32
+ `git diff --check`도 통과했다. 브로커 실서버 통합 검증은 수행하지 않았다.
@@ -0,0 +1,19 @@
1
+ # Inspector Console에서 사용자 지정 Task 이름으로 요청 시 큐 발행 전에 거부됨
2
+
3
+ ## 버전
4
+
5
+ 0.1.12
6
+
7
+ ## 내용
8
+
9
+ Inspector Console이 Task 목록에 표시하는 이름과 실제 Task를 찾는 기준이 다릅니다.
10
+
11
+ Specifications.document()은 task.name을 작업 ID로 사용합니다. Console UI는 이 ID를 선택해 요청을 보내지만, Console.execute()는 등록된 작업을 찾을 때 task.__name__과 요청의 task 값을 비교합니다.
12
+
13
+ 예를 들어 Orbis Split은 Split.name이 ETL.OBS.Split이고 Split.__name__은 Split입니다. 따라서 UI에서 선택한 작업 ID ETL.OBS.Split과 Console의 비교 값 Split이 일치하지 않아 Unknown registered task 오류가 발생합니다. 이 검사는 브로커에 연결하거나 메시지를 발행하기 전에 수행되므로 요청은 큐에 도달하지 않습니다.
14
+
15
+ 또한 Console 경고 로그에는 구체적인 오류 메시지 대신 예외 종류만 기록되어 원인을 파악하기 어렵습니다.
16
+
17
+ 기대 동작: Console이 Task 목록을 만들 때와 동일하게 task.name을 기준으로 작업을 찾아야 합니다. 중복 여부 검사도 같은 기준을 사용해야 합니다.
18
+
19
+ 실제 동작: Console이 task.__name__을 기준으로 작업을 찾아 사용자 지정 이름을 사용하는 Task를 거부합니다.
@@ -0,0 +1,12 @@
1
+ # Inspector Console 사용자 지정 Task 이름 처리
2
+
3
+ Inspector Console이 작업 목록에 표시한 ID로 Task를 찾도록 수정했습니다.
4
+ 따라서 `ETL.OBS.Split`처럼 클래스 이름과 다른 사용자 지정 Task 이름으로도
5
+ 요청을 보낼 수 있습니다. 동일한 작업 ID가 중복 등록된 경우에는 모호한 작업
6
+ 실행을 막기 위해 요청을 거부합니다.
7
+
8
+ 잘못된 요청은 기존처럼 거부되며, 경고 로그에 예외 종류와 구체적인 원인이 함께
9
+ 기록됩니다.
10
+
11
+ 세부 내용은 [요구사항 명세서](./REQUIREMENTS.md)와
12
+ [구현 및 검증 기록](./IMPLEMENTS.md)을 참고하세요.
@@ -0,0 +1,25 @@
1
+ # Inspector Console의 사용자 지정 Task 이름 처리 요구사항
2
+
3
+ ## 목적
4
+
5
+ Inspector Console이 Task 목록에 표시한 작업 ID로 등록된 Task를 찾아 실행하도록 한다. Task에 사용자 지정 이름이 지정되어 있어도 요청이 잘못 거부되거나 큐 발행 전에 중단되지 않아야 한다.
6
+
7
+ ## 배경
8
+
9
+ `Specifications.document()`은 `task.name`을 작업 ID로 사용하고, Console UI는 이 ID를 요청에 포함한다. 그러나 `Console.execute()`는 등록된 작업을 찾을 때 `task.__name__`과 요청의 작업 ID를 비교한다.
10
+
11
+ 예를 들어 `Split.name`이 `ETL.OBS.Split`이고 `Split.__name__`이 `Split`이면, 요청 ID `ETL.OBS.Split`과 비교 값이 달라 `Unknown registered task` 오류가 발생한다. 이 오류는 브로커 연결 및 메시지 발행 전에 발생하므로 요청이 큐에 도달하지 않는다.
12
+
13
+ ## 요구사항
14
+
15
+ 1. Console은 요청의 작업 ID와 등록된 Task의 `task.name`을 비교해 실행할 Task를 찾아야 한다.
16
+ 2. 중복 작업 ID 검사도 `task.name`을 기준으로 수행해야 한다. 같은 이름을 가진 등록 Task가 중복으로 허용되어서는 안 된다.
17
+ 3. 목록에 표시된 사용자 지정 작업 ID로 요청하면, 해당 Task를 찾지 못했다는 오류로 거부하지 않고 정상적인 실행 절차를 진행해야 한다.
18
+ 4. 요청 처리 중 오류가 발생하면 경고 로그에 예외 종류뿐 아니라 구체적인 오류 메시지도 기록해야 한다.
19
+
20
+ ## 완료 기준
21
+
22
+ - `task.name`과 `task.__name__`이 다른 Task를 목록의 작업 ID로 요청해도 올바른 Task가 선택된다.
23
+ - 중복 검사와 Task 검색이 모두 `task.name`을 기준으로 일관되게 동작한다.
24
+ - 유효한 사용자 지정 작업 ID 요청은 큐 발행 단계까지 진행되며, 해당 요청이 `Unknown registered task` 오류로 중단되지 않는다.
25
+ - 오류 로그에서 예외 종류와 구체적인 원인을 확인할 수 있다.
@@ -323,13 +323,13 @@ class Console(Extension):
323
323
  )
324
324
  task = next(
325
325
  (
326
- task for task in worker.tasks if task.__name__ == payload['task']
326
+ task for task in worker.tasks if task.name == payload['task']
327
327
  ),
328
328
  None,
329
329
  )
330
330
  if task is None:
331
331
  raise ValueError('Unknown registered task')
332
- if sum(task.__name__ == payload['task'] for task in worker.tasks) != 1:
332
+ if sum(task.name == payload['task'] for task in worker.tasks) != 1:
333
333
  raise ValueError('Ambiguous registered task name')
334
334
  except (
335
335
  ValueError,
@@ -337,8 +337,9 @@ class Console(Extension):
337
337
  UnicodeDecodeError,
338
338
  ) as error:
339
339
  self.logger.warning(
340
- 'Inspector Console rejected invalid input: error=%s',
340
+ 'Inspector Console rejected invalid input: error=%s message=%s',
341
341
  type(error).__name__,
342
+ error,
342
343
  )
343
344
  return json_response(
344
345
  '400 Bad Request',
@@ -57,6 +57,19 @@ class Task(
57
57
  return a / b
58
58
 
59
59
 
60
+ class NamedTask(
61
+ Run,
62
+ run_name='ETL.OBS.Split',
63
+ parameters={'queue': 'named-task'},
64
+ ):
65
+ def run(
66
+ self,
67
+ a,
68
+ b,
69
+ ):
70
+ return a / b
71
+
72
+
60
73
  class Producer:
61
74
  def __init__(self):
62
75
  self.connected = 0
@@ -168,7 +181,7 @@ class ConsoleExtensionTests(TestCase):
168
181
  mode='send',
169
182
  ):
170
183
  return {
171
- 'task': 'Task',
184
+ 'task': Task.name,
172
185
  'mode': mode,
173
186
  'body': {
174
187
  'a': 6,
@@ -459,6 +472,47 @@ class ConsoleExtensionTests(TestCase):
459
472
  self.worker.broker.connect.assert_not_called()
460
473
  self.worker.broker.close.assert_not_called()
461
474
 
475
+ def test_custom_task_name_is_resolved_and_duplicate_names_are_rejected(self):
476
+ self.worker.add(NamedTask)
477
+ payload = self.payload()
478
+ payload['task'] = NamedTask.name
479
+ status, body, headers = self.fetch(
480
+ 'POST',
481
+ payload,
482
+ )
483
+ self.assertEqual(status, 200)
484
+ self.assertEqual(loads(body)['result'], 'message-id')
485
+ self.assertEqual(self.producers[-1].sent[0][1], NamedTask.parameters)
486
+
487
+ self.worker.tasks.append(NamedTask)
488
+ with self.assertLogs(
489
+ 'DefStream.Inspector.Extensions.Console',
490
+ level='WARNING',
491
+ ) as logs:
492
+ status, body, headers = self.fetch(
493
+ 'POST',
494
+ payload,
495
+ )
496
+ self.assertEqual(status, 400)
497
+ self.assertEqual(loads(body)['error'], 'Ambiguous registered task name')
498
+ self.assertIn('message=Ambiguous registered task name', logs.output[0])
499
+
500
+ def test_invalid_task_warning_includes_the_specific_error(self):
501
+ payload = self.payload()
502
+ payload['task'] = 'not-registered'
503
+ with self.assertLogs(
504
+ 'DefStream.Inspector.Extensions.Console',
505
+ level='WARNING',
506
+ ) as logs:
507
+ status, body, headers = self.fetch(
508
+ 'POST',
509
+ payload,
510
+ )
511
+ self.assertEqual(status, 400)
512
+ self.assertIn('error=ValueError', logs.output[0])
513
+ self.assertIn('message=Unknown registered task', logs.output[0])
514
+ self.assertEqual(self.producers, [])
515
+
462
516
  def test_unsupported_rpc_and_worker_not_running(self):
463
517
  self.extension.broker = Producer
464
518
  self.assertFalse(loads(self.fetch()[1])['rpc'])
@@ -768,7 +822,7 @@ class ConsoleExtensionTests(TestCase):
768
822
  rpc,
769
823
  )
770
824
  payload = self.payload()
771
- payload['task'] = 'Live'
825
+ payload['task'] = Live.name
772
826
  self.assertEqual(
773
827
  self.fetch(
774
828
  'POST',
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes