jetstream-api 0.20.0__tar.gz → 0.20.2__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 (30) hide show
  1. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/PKG-INFO +48 -1
  2. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/README.md +47 -0
  3. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/__init__.py +11 -1
  4. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/_qleader.py +48 -0
  5. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/admin.py +517 -0
  6. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/common.py +22 -0
  7. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/properties.py +284 -2
  8. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/qmgr.py +65 -19
  9. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/jetstream_api.egg-info/PKG-INFO +48 -1
  10. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/pyproject.toml +1 -1
  11. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/LICENSE.txt +0 -0
  12. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/_codec.py +0 -0
  13. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/_consumer.py +0 -0
  14. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/_groupwire.py +0 -0
  15. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/admintopic.py +0 -0
  16. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/connectivity.py +0 -0
  17. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/exception.py +0 -0
  18. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/msg.py +0 -0
  19. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/partitioner.py +0 -0
  20. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/pattern.py +0 -0
  21. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/producer.py +0 -0
  22. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/py.typed +0 -0
  23. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/topic.py +0 -0
  24. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/ilink/util.py +0 -0
  25. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/jetstream_api.egg-info/SOURCES.txt +0 -0
  26. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/jetstream_api.egg-info/dependency_links.txt +0 -0
  27. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/jetstream_api.egg-info/requires.txt +0 -0
  28. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/jetstream_api.egg-info/top_level.txt +0 -0
  29. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/setup.cfg +0 -0
  30. {jetstream_api-0.20.0 → jetstream_api-0.20.2}/tests/test_example.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetstream-api
3
- Version: 0.20.0
3
+ Version: 0.20.2
4
4
  Summary: Python client API for iLink M.O.M. (Message Oriented Middleware)
5
5
  Author: snowjeans
6
6
  License: Boost Software License - Version 1.0 - August 17th, 2003
@@ -60,6 +60,53 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
60
60
  ## 설치 방법
61
61
  pip install jetstream-api
62
62
 
63
+ ## 0.20.2 변경 - 관제 명령 관리 API · 강제 선출 · 리더십 표 · 격리본 (자바 v2.16.2 와 같음, 짝 엔진 7.0.1.3512 이상 - 리더십 표 · 격리본 · 키 단위 강제 선출은 7.0.1.3552 이상)
64
+
65
+ - **리더십 표 · 격리본**(엔진 7.0.1.3552 이상, 그 전 엔진은 `MIMQE_INVALID_REQ_CODE`):
66
+ - `ILAdminService.getClusterLeadTable(cluster)`(VIEW CLUSTER LEADERS, 3423): 원문. `getClusterLeadTableParsed` 는
67
+ `ILClusterLeadTable`(노드 · 파티션 · 묶음 행, 강제 선출 기록, 오프라인 행)로 풀어 준다. 모르는 줄은 건너뛰고, 판(`ILLT1`)이 다르면 거절.
68
+ - `ILAdminQmgr.getQuarantineList()` / `scanQuarantine(dir, queue, since)`(VIEW QUARANTINE, 3425 / 3426): 원문.
69
+ - `reinjectQuarantine(dir, queue, since)`(REINJECT, 3427): `ILQuarantineReinjectResult`(건수 · 리더 · 멈춘 사유). ☠ OLD 까지
70
+ 넣으면 중복 가능, 넣은 건은 큐 맨 뒤에 붙는다.
71
+
72
+ - **ilsc 관제 명령을 관리 API 로**(엔진이 이미 받는 요청에 클라 메서드만 없던 것):
73
+ - `ILAdminService.shutdownService(clusterWide=False)`(SHUTDOWN, 3002): 응답 없이 끊기면 False(엔진이 내려가며 닫음), 시간 초과는 예외.
74
+ - `patchService(fileName, data)`(PATCH, 3335): 성공하면 서비스가 다시 기동하고 연결이 닫힌다.
75
+ - `diagnoseClusterDefinition(clusterName)`(DIAG CLUSTER 의 정의 대조, 3395): 텍스트 그대로.
76
+ - `ILAdminQmgr.getLoadMonitoringInfo(level)`(VIEW LOAD, 3204), `reloadQueue`(RELOAD QUEUE, 3315),
77
+ `setChannelStartMode(channel, autoStart)`(가동 중 STARTMODE, 3035), `removeMessagesFifo(queue, count)`(앞에서부터 지우기, 3345).
78
+ - `ILClusterProperty.placement` / `autoRebalance`(PLACEMENT · AUTOREBALANCE): `None` 은 보낼 때 "그대로 둔다",
79
+ `"DEFAULT"` 는 미설정으로 되돌린다.
80
+
81
+ - **내부 테스트 자동화 전용** `ILAdminService.checkForceElectLeader` / `forceElectLeader`(+ snake 별칭): 엔진 7.0.1.3551 의 운영자
82
+ 강제 선출(`ELECT CLUSTER(C) LEADER(..) FORCE`, 요청 3422)을 관리 API 로 부른다. 확인(위험만 봄)과 실행(☠ 유실 감수)을 나눴고,
83
+ 키(`"<토픽>/<파티션>"` / `"Q:<묶음>/0"`, 도우미 `forceElectPartitionKey` / `forceElectGroupKey`)로 하나만 강제할 수도 있다 -
84
+ 키 단위는 엔진 7.0.1.3552 이상(그 전 엔진은 키를 버리고 노드 단위로 실행하므로 옛 엔진임이 확실하면 보내기 전에 막는다).
85
+ 결과는 `ILClusterForceElectResult`(target · state · risk). 클라는 다시 보내지 않는다(실행의 결과 모름은 확인부터).
86
+ 지금은 내부 시험 자동화에서만 쓴다 - 운영자의 강제 선출은 ilsc 로 한다.
87
+
88
+ - `removeNode` 문서: `MIMQE_CLUSTER_NOT_COMMITTED (not committed - retry)` 는 실패가 아니라 **결과 모름**입니다(컨트롤러가 8초 안에
89
+ 확정을 못 봄, 늦게 확정될 수 있음). 클라는 스스로 다시 보내지 않습니다. 다시 불러도 안전하고, 그때 `MIMQE_OBJECT_NOT_FOUND` 면
90
+ 먼저 것이 확정돼 이미 빠진 것입니다. 클라 동작은 바뀌지 않습니다.
91
+
92
+ ## 0.20.1 변경 - 큐 묶음 이동 중 재시도 (자바 v2.16.1 과 같음, 짝 엔진 7.0.1.3512 이상 - 묶음 이동은 7.0.1.3550 이상의 묶음 모드)
93
+
94
+ - 큐 묶음 이동(엔진 7.0.1.3550 3-b3, `ALTER QUEUE … LEADERGROUP` 등)이 진행 중이면 엔진이 그 큐의 요청을
95
+ `MIMQE_QUEUE_MOVING (<큐> -> group <새 묶음>)` 으로 거절합니다(요청 입구에서 작업 전 - 적용 안 됨 확정). 자동 확인 세션은 이것을
96
+ 앱에 올리지 않고 100ms → 1초로 쉬며 리더를 다시 묻고 세션 타임아웃까지 다시 보냅니다(이동은 보통 1초 안팎). 끝내 이동이 안 끝나면
97
+ 그 사유로 실패합니다. 트랜잭션 세션은 지금처럼 올립니다(커밋이면 엔진이 롤백 - 트랜잭션을 처음부터). 0.20.0 은 이 사유를 그대로
98
+ 올렸습니다.
99
+
100
+ - 큐 속성 `leaderGroup` 문서: 큐가 하나도 없는 새 묶음으로 옮기면 첫 시도가
101
+ `MIMQE_QUEUE_MOVE_REFUSED (group <묶음> has no leader yet - retry)` 로 거절될 수 있습니다(엔진 7.0.1.3550 이상, 속성은 바뀌지
102
+ 않음 - 함께 실린 다른 속성 변경도 적용되지 않는 요청 전체 거절). 관리 요청은 클라가 다시 보내지 않으니 몇 초 뒤 같은 객체로
103
+ `setQueueProperty` 를 다시 부릅니다. 클라 동작은 바뀌지 않습니다.
104
+
105
+ - 큐 자동 확인 세션의 `get` / `gets`: "at-most-once" 라고만 적었던 것을 "**한 번만 온다고 보장하지 않는다**" 로 고쳤습니다.
106
+ 받는 도중 수신 시간이 다하면 다시 오지 않는 것(유실)은 그대로이고, 클러스터에서는 리더 장애 순간에 받은 메시지가 새 리더에서
107
+ **한 번 더** 올 수 있습니다(at-least-once - 엔진 큐 묶음 리더 판 7.0.1.3550 의 규칙, 2026-10-03 결정). 중복을 견뎌야 하면 메시지
108
+ ID 로 거르거나 트랜잭션 세션으로 받습니다. 클라 동작은 바뀌지 않습니다.
109
+
63
110
  ## 0.20.0 변경 - 큐 묶음 리더 라우팅, 큐 속성 leaderGroup (자바 v2.16.0 과 같음, 짝 엔진 7.0.1.3512 이상)
64
111
 
65
112
  > 큐 묶음(LEADERGROUP) 라우팅은 엔진 **7.0.1.3540** 이상에서 묶음 모드가 켜졌을 때만 동작합니다(묶음 모드는 엔진 3-b3 에서 켜집니다).
@@ -10,6 +10,53 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
10
10
  ## 설치 방법
11
11
  pip install jetstream-api
12
12
 
13
+ ## 0.20.2 변경 - 관제 명령 관리 API · 강제 선출 · 리더십 표 · 격리본 (자바 v2.16.2 와 같음, 짝 엔진 7.0.1.3512 이상 - 리더십 표 · 격리본 · 키 단위 강제 선출은 7.0.1.3552 이상)
14
+
15
+ - **리더십 표 · 격리본**(엔진 7.0.1.3552 이상, 그 전 엔진은 `MIMQE_INVALID_REQ_CODE`):
16
+ - `ILAdminService.getClusterLeadTable(cluster)`(VIEW CLUSTER LEADERS, 3423): 원문. `getClusterLeadTableParsed` 는
17
+ `ILClusterLeadTable`(노드 · 파티션 · 묶음 행, 강제 선출 기록, 오프라인 행)로 풀어 준다. 모르는 줄은 건너뛰고, 판(`ILLT1`)이 다르면 거절.
18
+ - `ILAdminQmgr.getQuarantineList()` / `scanQuarantine(dir, queue, since)`(VIEW QUARANTINE, 3425 / 3426): 원문.
19
+ - `reinjectQuarantine(dir, queue, since)`(REINJECT, 3427): `ILQuarantineReinjectResult`(건수 · 리더 · 멈춘 사유). ☠ OLD 까지
20
+ 넣으면 중복 가능, 넣은 건은 큐 맨 뒤에 붙는다.
21
+
22
+ - **ilsc 관제 명령을 관리 API 로**(엔진이 이미 받는 요청에 클라 메서드만 없던 것):
23
+ - `ILAdminService.shutdownService(clusterWide=False)`(SHUTDOWN, 3002): 응답 없이 끊기면 False(엔진이 내려가며 닫음), 시간 초과는 예외.
24
+ - `patchService(fileName, data)`(PATCH, 3335): 성공하면 서비스가 다시 기동하고 연결이 닫힌다.
25
+ - `diagnoseClusterDefinition(clusterName)`(DIAG CLUSTER 의 정의 대조, 3395): 텍스트 그대로.
26
+ - `ILAdminQmgr.getLoadMonitoringInfo(level)`(VIEW LOAD, 3204), `reloadQueue`(RELOAD QUEUE, 3315),
27
+ `setChannelStartMode(channel, autoStart)`(가동 중 STARTMODE, 3035), `removeMessagesFifo(queue, count)`(앞에서부터 지우기, 3345).
28
+ - `ILClusterProperty.placement` / `autoRebalance`(PLACEMENT · AUTOREBALANCE): `None` 은 보낼 때 "그대로 둔다",
29
+ `"DEFAULT"` 는 미설정으로 되돌린다.
30
+
31
+ - **내부 테스트 자동화 전용** `ILAdminService.checkForceElectLeader` / `forceElectLeader`(+ snake 별칭): 엔진 7.0.1.3551 의 운영자
32
+ 강제 선출(`ELECT CLUSTER(C) LEADER(..) FORCE`, 요청 3422)을 관리 API 로 부른다. 확인(위험만 봄)과 실행(☠ 유실 감수)을 나눴고,
33
+ 키(`"<토픽>/<파티션>"` / `"Q:<묶음>/0"`, 도우미 `forceElectPartitionKey` / `forceElectGroupKey`)로 하나만 강제할 수도 있다 -
34
+ 키 단위는 엔진 7.0.1.3552 이상(그 전 엔진은 키를 버리고 노드 단위로 실행하므로 옛 엔진임이 확실하면 보내기 전에 막는다).
35
+ 결과는 `ILClusterForceElectResult`(target · state · risk). 클라는 다시 보내지 않는다(실행의 결과 모름은 확인부터).
36
+ 지금은 내부 시험 자동화에서만 쓴다 - 운영자의 강제 선출은 ilsc 로 한다.
37
+
38
+ - `removeNode` 문서: `MIMQE_CLUSTER_NOT_COMMITTED (not committed - retry)` 는 실패가 아니라 **결과 모름**입니다(컨트롤러가 8초 안에
39
+ 확정을 못 봄, 늦게 확정될 수 있음). 클라는 스스로 다시 보내지 않습니다. 다시 불러도 안전하고, 그때 `MIMQE_OBJECT_NOT_FOUND` 면
40
+ 먼저 것이 확정돼 이미 빠진 것입니다. 클라 동작은 바뀌지 않습니다.
41
+
42
+ ## 0.20.1 변경 - 큐 묶음 이동 중 재시도 (자바 v2.16.1 과 같음, 짝 엔진 7.0.1.3512 이상 - 묶음 이동은 7.0.1.3550 이상의 묶음 모드)
43
+
44
+ - 큐 묶음 이동(엔진 7.0.1.3550 3-b3, `ALTER QUEUE … LEADERGROUP` 등)이 진행 중이면 엔진이 그 큐의 요청을
45
+ `MIMQE_QUEUE_MOVING (<큐> -> group <새 묶음>)` 으로 거절합니다(요청 입구에서 작업 전 - 적용 안 됨 확정). 자동 확인 세션은 이것을
46
+ 앱에 올리지 않고 100ms → 1초로 쉬며 리더를 다시 묻고 세션 타임아웃까지 다시 보냅니다(이동은 보통 1초 안팎). 끝내 이동이 안 끝나면
47
+ 그 사유로 실패합니다. 트랜잭션 세션은 지금처럼 올립니다(커밋이면 엔진이 롤백 - 트랜잭션을 처음부터). 0.20.0 은 이 사유를 그대로
48
+ 올렸습니다.
49
+
50
+ - 큐 속성 `leaderGroup` 문서: 큐가 하나도 없는 새 묶음으로 옮기면 첫 시도가
51
+ `MIMQE_QUEUE_MOVE_REFUSED (group <묶음> has no leader yet - retry)` 로 거절될 수 있습니다(엔진 7.0.1.3550 이상, 속성은 바뀌지
52
+ 않음 - 함께 실린 다른 속성 변경도 적용되지 않는 요청 전체 거절). 관리 요청은 클라가 다시 보내지 않으니 몇 초 뒤 같은 객체로
53
+ `setQueueProperty` 를 다시 부릅니다. 클라 동작은 바뀌지 않습니다.
54
+
55
+ - 큐 자동 확인 세션의 `get` / `gets`: "at-most-once" 라고만 적었던 것을 "**한 번만 온다고 보장하지 않는다**" 로 고쳤습니다.
56
+ 받는 도중 수신 시간이 다하면 다시 오지 않는 것(유실)은 그대로이고, 클러스터에서는 리더 장애 순간에 받은 메시지가 새 리더에서
57
+ **한 번 더** 올 수 있습니다(at-least-once - 엔진 큐 묶음 리더 판 7.0.1.3550 의 규칙, 2026-10-03 결정). 중복을 견뎌야 하면 메시지
58
+ ID 로 거르거나 트랜잭션 세션으로 받습니다. 클라 동작은 바뀌지 않습니다.
59
+
13
60
  ## 0.20.0 변경 - 큐 묶음 리더 라우팅, 큐 속성 leaderGroup (자바 v2.16.0 과 같음, 짝 엔진 7.0.1.3512 이상)
14
61
 
15
62
  > 큐 묶음(LEADERGROUP) 라우팅은 엔진 **7.0.1.3540** 이상에서 묶음 모드가 켜졌을 때만 동작합니다(묶음 모드는 엔진 3-b3 에서 켜집니다).
@@ -1,6 +1,6 @@
1
1
  """iLink - Python client API for iLink M.O.M. (Message Oriented Middleware)."""
2
2
 
3
- __version__ = "0.20.0"
3
+ __version__ = "0.20.2"
4
4
 
5
5
  # --- Admin / Service ---
6
6
  from .admin import ILAdminService, ILAdminQmgr, ILLogBrowser, ILQueueBrowser
@@ -29,6 +29,11 @@ from .properties import (
29
29
  ILClusterNode,
30
30
  ILClusterControlResult,
31
31
  ILClusterDissolveResult,
32
+ ILClusterForceElectResult,
33
+ ILClusterLeadTable,
34
+ ILClusterLeadEntry,
35
+ ILClusterForcedKey,
36
+ ILQuarantineReinjectResult,
32
37
  ILClusterJoinResult,
33
38
  ILClusterNodeAddResult,
34
39
  ILFollowerStatus,
@@ -90,6 +95,11 @@ __all__ = [
90
95
  "ILClusterNode",
91
96
  "ILClusterControlResult",
92
97
  "ILClusterDissolveResult",
98
+ "ILClusterForceElectResult",
99
+ "ILClusterLeadTable",
100
+ "ILClusterLeadEntry",
101
+ "ILClusterForcedKey",
102
+ "ILQuarantineReinjectResult",
93
103
  "ILClusterJoinResult",
94
104
  "ILClusterNodeAddResult",
95
105
  "ILFollowerStatus",
@@ -108,6 +108,34 @@ def follower_hint(reason: str):
108
108
  return (tok, nid)
109
109
 
110
110
 
111
+ def is_moving(reason: str) -> bool:
112
+ """큐 묶음 이동 중 거절인가(0.20.1, 엔진 3-b3).
113
+
114
+ ``MIMQE_QUEUE_MOVING (<큐> -> group <새 묶음>)`` / ``(... (node leader))`` / ``(retry shortly)``. 엔진은 요청 입구에서 작업 전에
115
+ 거절하므로 **그 요청은 적용되지 않았다**(엔진 확인). 리더 힌트는 없다 - 이동이 끝난 뒤 3397 "Q" 로 다시 묻는다. 이동은 보통
116
+ 1초 안팎, 최악이면 수십 초다.
117
+
118
+ Args:
119
+ reason (str): 엔진 사유(arg2).
120
+
121
+ Returns:
122
+ bool: 이동 중 거절이면 True.
123
+ """
124
+ return bool(reason) and reason.startswith("MIMQE_QUEUE_MOVING (")
125
+
126
+
127
+ def route_rejected(reason: str) -> bool:
128
+ """라우팅 거절(적용 안 됨 확정)인가 - 요청 단위 팔로워 거절 또는 묶음 이동 중.
129
+
130
+ Args:
131
+ reason (str): 엔진 사유(arg2).
132
+
133
+ Returns:
134
+ bool: 둘 중 하나면 True.
135
+ """
136
+ return follower_hint(reason) is not None or is_moving(reason)
137
+
138
+
111
139
  def cross_error(have: str, want: str) -> ILOperationException:
112
140
  """한 트랜잭션에 다른 묶음 큐를 섞으려 할 때의 오류(엔진 사유와 같은 머리).
113
141
 
@@ -315,6 +343,26 @@ class QueueRouter:
315
343
  self.lookup([name])
316
344
  return True
317
345
 
346
+ def forget_queue(self, name: str) -> None:
347
+ """그 큐의 묶음 소속만 버린다 - 묶음 이동으로 소속이 바뀔 때. 다음 요청이 다시 묻는다.
348
+
349
+ Args:
350
+ name (str): 큐 이름.
351
+ """
352
+ with self.lock:
353
+ self.q_group.pop(name, None)
354
+
355
+ def on_moving(self, name: str, pause: float) -> None:
356
+ """묶음 이동 중 거절을 받았다 - 소속을 버리고 ``pause`` 초 쉰 뒤 다시 묻는다(0.20.1).
357
+
358
+ Args:
359
+ name (str): 큐 이름.
360
+ pause (float): 쉴 시간(초).
361
+ """
362
+ self.forget_queue(name)
363
+ time.sleep(pause)
364
+ self.lookup([name])
365
+
318
366
  def forget_group(self, grp: str | None) -> None:
319
367
  """그 묶음의 리더와 그 묶음 큐들의 소속을 버린다 - 다음 요청이 다시 묻는다.
320
368