jetstream-api 0.7.1__tar.gz → 0.7.3__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 (26) hide show
  1. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/PKG-INFO +65 -1
  2. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/README.md +64 -0
  3. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/__init__.py +1 -1
  4. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/admin.py +6 -3
  5. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/common.py +7 -0
  6. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/connectivity.py +502 -15
  7. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/msg.py +300 -33
  8. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/pattern.py +284 -65
  9. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/producer.py +293 -146
  10. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/properties.py +5 -4
  11. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/qmgr.py +155 -20
  12. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/topic.py +535 -133
  13. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/jetstream_api.egg-info/PKG-INFO +65 -1
  14. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/pyproject.toml +1 -1
  15. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/LICENSE.txt +0 -0
  16. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/admintopic.py +0 -0
  17. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/exception.py +0 -0
  18. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/partitioner.py +0 -0
  19. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/py.typed +0 -0
  20. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/ilink/util.py +0 -0
  21. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/jetstream_api.egg-info/SOURCES.txt +0 -0
  22. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/jetstream_api.egg-info/dependency_links.txt +0 -0
  23. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/jetstream_api.egg-info/requires.txt +0 -0
  24. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/jetstream_api.egg-info/top_level.txt +0 -0
  25. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/setup.cfg +0 -0
  26. {jetstream_api-0.7.1 → jetstream_api-0.7.3}/tests/test_example.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetstream-api
3
- Version: 0.7.1
3
+ Version: 0.7.3
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
@@ -54,6 +54,70 @@ Python으로 작성된 ILink 클라이언트 API입니다.
54
54
  ## 설치 방법
55
55
  pip install jetstream-api
56
56
 
57
+ ## 0.7.3 변경 - 구독마다 전용 연결, 소비 프로토콜 v5, 발행 / 소비 CPU 절감 (자바 v2.3.4 와 같음)
58
+
59
+ - **엔진 요구**: 토픽 구독은 **엔진 7.0.1.3415 이상**(소비 프로토콜 v5)에서만 동작합니다. 그보다 옛 엔진은 요청 태그를
60
+ 모르므로 구독 연결을 끊습니다. 발행과 큐 기능은 영향이 없습니다.
61
+ - **구독마다 전용 연결**: 구독(패턴 구독이면 패턴 하나)마다 엔진 세션을 하나 따로 엽니다(클라이언트 이름 `<이름>-SUB`).
62
+ 한 구독이 레코드를 기다려도 다른 구독이나 같은 `ILQmgr` 의 큐 / 관리 요청이 기다리지 않습니다. 대신 큐 관리자의 세션
63
+ 수가 구독 수만큼 늘어납니다. 구독을 `close()` 하면 그 세션이 닫히고(엔진은 곧바로 멤버를 빼고 재배정합니다),
64
+ `ILQmgr.disconnect()` 는 그 세션에서 만든 구독을 모두 닫으며, `reconnect()` 는 구독 세션도 함께 다시 붙입니다.
65
+ `close()` 뒤의 read / commit 은 오류입니다. 다른 스레드의 read 가 레코드를 기다리던 중에 `close()` 하면 그 read 도 곧바로
66
+ 끝납니다.
67
+ - **`close()` 와 `unsubscribe()` 의 차이**: `close()` 는 **이 멤버만** 빠집니다(연결을 끊으면 엔진이 곧바로 멤버를 빼고 재배정하며,
68
+ 커서는 남습니다). `unsubscribe()` 는 **구독(그룹) 자체를 지웁니다** - 모든 파티션의 커서(durable 포함)가 사라지고, 같은
69
+ 구독 이름으로 붙어 있는 다른 멤버(다른 프로세스 포함)도 다음 read 에서 `MIMQE_TOPIC_SUBSCRIPTION_NOT_FOUND` 를 받습니다.
70
+ 구독을 없앨 때만 부르세요. `unsubscribe()` 는 `close()` 뒤에도 됩니다(`ILQmgr` 의 연결로 보냅니다).
71
+ 구독 세션은 `ILQmgr` 의 세션 모드와 상관없이 **늘 자동 확인 모드**로 열립니다 - 토픽 read / commit / seek 는 원래 세션
72
+ 트랜잭션에 묶이지 않으므로(`qmgr.commit()` / `rollback()` 은 큐만 다룹니다) 동작은 그대로입니다.
73
+ - **소비 프로토콜 v5**: 구독 연결의 요청에 태그를 붙여 겹쳐 보냅니다 - 레코드를 기다리는 동안에도 같은 구독의
74
+ commit / seek 가 곧바로 처리됩니다(한 구독의 read 는 하나씩 나갑니다). 패턴 구독은 매칭된 토픽 전체를 요청 한 번(다중 토픽
75
+ read)으로 받습니다. 커밋 좌표는 파티션 수와 관계없이 **한 요청**에 실리고, 한 요청 전체가 되거나 안 되거나입니다 - 이 멤버에게
76
+ 배정되지 않은 파티션이 하나라도 있으면 `MIMQE_TOPIC_REBALANCED (partition N is not owned by this member)` 로 아무것도
77
+ 커밋되지 않습니다.
78
+
79
+ - **정확성**:
80
+ - 한 `ILQmgr` 에서 `listen()` 구독이 둘 이상이거나, `listen()` 중에 같은 `ILQmgr` 로 다른 요청(큐 put/get, 관리 요청,
81
+ 다른 구독의 read)을 하면 소켓 하나에서 요청과 응답이 섞일 수 있었습니다. 이제 연결마다 잠금 하나로 요청-응답을 짝 단위로
82
+ 줄 세웁니다(먼저 기다린 쪽이 먼저).
83
+ - `listen()` 콜백이 예외를 던져 멈추면, 뒤이은 `close()` 가 처리하지 않은 레코드까지 AUTO 커밋하던 결함을 고쳤습니다.
84
+ 이제 콜백이 정상으로 끝난 레코드만 커밋 대상이고, 콜백하지 못한 레코드는 같은 핸들의 다음 read / listen 이 다시 줍니다.
85
+ - `seek_to_offset(offset, partition)` 이 **다른 파티션**의 받아 두기만 한 레코드와 AUTO 커밋 좌표까지 버리던 결함을
86
+ 고쳤습니다(0.7.2 에도 있었습니다). 엔진은 지정한 파티션만 되감으므로 버려진 다른 파티션 구간은 다시 오지 않았고, AUTO 는
87
+ 뒤 커밋이 그 구간을 건너뛰었습니다. 이제 지정한 파티션만 버리고, seek 응답보다 먼저 도착한(곧 seek 전 위치에서 읽은) 그
88
+ 파티션의 레코드는 앱에 주지 않습니다. `partition` 을 생략하면 엔진은 **0번 파티션 하나만** 되감습니다(`offset=0` 이어도
89
+ 구독 전체가 아닙니다). 예전에는 이때도 모든 파티션의 받아 둔 레코드를 버렸습니다 - 이제 `;partition:0` 을 붙여 보내고 0번
90
+ 것만 버립니다. `seek_to_time()` 은 전 파티션을 되감으므로 전부 버립니다.
91
+ - seek 는 엔진이 멤버를 보지 않고 커서를 옮깁니다. 이 멤버에게 배정된 파티션만 되감고(`get_assignment()`), `seek_to_time()` 은
92
+ 그룹에 멤버가 하나일 때만 쓰세요.
93
+ - `close()` 의 AUTO 커밋이 `MIMQE_TOPIC_REBALANCED (partition N is not owned by this member)` 로 거절되면 그 파티션을 빼고
94
+ 다시 보냅니다 - 아직 소유한 파티션의 좌표는 반영됩니다(예전에는 전부 버려져 다음 멤버에게 다시 갔습니다).
95
+ - **문서**: 세션 목록(`ILSessionProperty`)의 `destroyedTime` 은 살아 있는 세션에서 **-1** 입니다(0 이 아닙니다). 끊긴 세션은
96
+ 끊긴 시각(epoch 밀리초)입니다. 살아 있는지는 `status` 로 판정하세요.
97
+ - **발행 CPU**: `send()` 가 레코드를 배치 버퍼에 곧바로 붙이고, 잠금 / 파티션 선택 / 키 인코딩 비용을 줄였습니다(레코드당 약 30% 감소).
98
+ - **소비 CPU**: 저장 v4 배치 응답을 풀면서 레코드 객체를 바로 만들고, AUTO 커밋 병합을 파티션마다 한 번 합니다(`read_batch` 약 40% 감소).
99
+ - **소비 왕복**:
100
+ - `read()` 가 AUTO / MANUAL 에서 prefetch 건수(기본 500)까지 한 번에 받아 두고 차례로 줍니다(레코드마다 왕복하지 않습니다).
101
+ IMMEDIATE 는 지금처럼 1건씩 요청합니다. 받아 두기만 한 레코드는 커밋되지 않으며, AUTO 커밋은 다음 요청(또는 `close()`)에 실립니다.
102
+ - `commit(list)` / `close()` 가 파티션마다 가장 큰 오프셋을 모아 파티션 수와 관계없이 한 요청으로 커밋합니다.
103
+ - `listen()` 과 prefetch 기본 배치가 100 에서 500 이 됐습니다.
104
+ - **패턴 구독**: `read` / `read_batch` 한 번이 매칭된 토픽 전체를 다중 토픽 read 요청 하나로 묻습니다. 한 토픽이라도 레코드가
105
+ 있으면 곧바로 돌아오고, 모두 비었으면 `timeout_ms` 동안 어느 토픽이든 들어오기를 기다립니다 - 한가한 토픽이 많아도 바쁜 토픽이
106
+ 늦어지지 않습니다. 한 번에 토픽 하나가 가져가는 양은 `bufferPerTopic` 으로 묶고, 시작 토픽을 호출마다 한 칸씩 돌립니다(바쁜
107
+ 토픽이 셋 이상일 때 하나를 건너뛰던 결함을 고쳤습니다). 목록 `commit` 은 토픽마다 한 요청이며, 보내기 전에 전부 검사합니다
108
+ (출처가 없는 레코드가 있으면 아무것도 커밋하지 않습니다).
109
+
110
+ ## 0.7.2 변경 - batchSize 기본값 262144 로 되돌림, 발행 경로 CPU 절감 (자바 v2.3.2 와 같음)
111
+
112
+ - `batchSize` 기본값을 **262144** 로 되돌렸습니다. 0.7.1 의 16384 에서 파이썬 클라는 처리량이 24~35% 낮았습니다(GIL 이
113
+ 천장이라 배치마다 드는 비용이 그대로 처리량에서 빠집니다). 멱등 기본 켜짐은 그대로입니다.
114
+ - 발행 경로 CPU 를 줄였습니다(API 는 그대로입니다). 레코드 future 가 배치 결과 하나를 함께 가리키고(완결은 배치당 한 번),
115
+ 키 -> 파티션 결과를 캐시하고, `send()` 가 설정값을 레코드마다 다시 읽지 않고, I/O 스레드를 깨우는 신호를 합치고,
116
+ ACK 하나의 배치 완결을 잠금 한 번에 묶습니다.
117
+ - producer 는 만들 때 설정 객체를 **복사**합니다(자바 v2.3.2 도 같고, Kafka 와 같습니다). 만든 뒤 넘긴 객체를 바꿔도 그
118
+ producer 에는 반영되지 않습니다 - 설정을 바꾸려면 producer 를 새로 만드십시오.
119
+ - 문서: 멱등이 거르는 것은 producer 안의 재전송뿐입니다 - 앱이 `send` 를 다시 부르면 새 레코드로 적재됩니다.
120
+
57
121
  ## 0.7.1 변경 - producer 기본값: 멱등 켜짐, batchSize 16384 (자바 v2.3.1 과 같음)
58
122
 
59
123
  - `enableIdempotence` 기본값이 **켜짐**입니다. 멱등을 직접 정하지 않았으면 `acks(0)` 이나 `maxInFlight` 가 5 를 넘을 때
@@ -8,6 +8,70 @@ Python으로 작성된 ILink 클라이언트 API입니다.
8
8
  ## 설치 방법
9
9
  pip install jetstream-api
10
10
 
11
+ ## 0.7.3 변경 - 구독마다 전용 연결, 소비 프로토콜 v5, 발행 / 소비 CPU 절감 (자바 v2.3.4 와 같음)
12
+
13
+ - **엔진 요구**: 토픽 구독은 **엔진 7.0.1.3415 이상**(소비 프로토콜 v5)에서만 동작합니다. 그보다 옛 엔진은 요청 태그를
14
+ 모르므로 구독 연결을 끊습니다. 발행과 큐 기능은 영향이 없습니다.
15
+ - **구독마다 전용 연결**: 구독(패턴 구독이면 패턴 하나)마다 엔진 세션을 하나 따로 엽니다(클라이언트 이름 `<이름>-SUB`).
16
+ 한 구독이 레코드를 기다려도 다른 구독이나 같은 `ILQmgr` 의 큐 / 관리 요청이 기다리지 않습니다. 대신 큐 관리자의 세션
17
+ 수가 구독 수만큼 늘어납니다. 구독을 `close()` 하면 그 세션이 닫히고(엔진은 곧바로 멤버를 빼고 재배정합니다),
18
+ `ILQmgr.disconnect()` 는 그 세션에서 만든 구독을 모두 닫으며, `reconnect()` 는 구독 세션도 함께 다시 붙입니다.
19
+ `close()` 뒤의 read / commit 은 오류입니다. 다른 스레드의 read 가 레코드를 기다리던 중에 `close()` 하면 그 read 도 곧바로
20
+ 끝납니다.
21
+ - **`close()` 와 `unsubscribe()` 의 차이**: `close()` 는 **이 멤버만** 빠집니다(연결을 끊으면 엔진이 곧바로 멤버를 빼고 재배정하며,
22
+ 커서는 남습니다). `unsubscribe()` 는 **구독(그룹) 자체를 지웁니다** - 모든 파티션의 커서(durable 포함)가 사라지고, 같은
23
+ 구독 이름으로 붙어 있는 다른 멤버(다른 프로세스 포함)도 다음 read 에서 `MIMQE_TOPIC_SUBSCRIPTION_NOT_FOUND` 를 받습니다.
24
+ 구독을 없앨 때만 부르세요. `unsubscribe()` 는 `close()` 뒤에도 됩니다(`ILQmgr` 의 연결로 보냅니다).
25
+ 구독 세션은 `ILQmgr` 의 세션 모드와 상관없이 **늘 자동 확인 모드**로 열립니다 - 토픽 read / commit / seek 는 원래 세션
26
+ 트랜잭션에 묶이지 않으므로(`qmgr.commit()` / `rollback()` 은 큐만 다룹니다) 동작은 그대로입니다.
27
+ - **소비 프로토콜 v5**: 구독 연결의 요청에 태그를 붙여 겹쳐 보냅니다 - 레코드를 기다리는 동안에도 같은 구독의
28
+ commit / seek 가 곧바로 처리됩니다(한 구독의 read 는 하나씩 나갑니다). 패턴 구독은 매칭된 토픽 전체를 요청 한 번(다중 토픽
29
+ read)으로 받습니다. 커밋 좌표는 파티션 수와 관계없이 **한 요청**에 실리고, 한 요청 전체가 되거나 안 되거나입니다 - 이 멤버에게
30
+ 배정되지 않은 파티션이 하나라도 있으면 `MIMQE_TOPIC_REBALANCED (partition N is not owned by this member)` 로 아무것도
31
+ 커밋되지 않습니다.
32
+
33
+ - **정확성**:
34
+ - 한 `ILQmgr` 에서 `listen()` 구독이 둘 이상이거나, `listen()` 중에 같은 `ILQmgr` 로 다른 요청(큐 put/get, 관리 요청,
35
+ 다른 구독의 read)을 하면 소켓 하나에서 요청과 응답이 섞일 수 있었습니다. 이제 연결마다 잠금 하나로 요청-응답을 짝 단위로
36
+ 줄 세웁니다(먼저 기다린 쪽이 먼저).
37
+ - `listen()` 콜백이 예외를 던져 멈추면, 뒤이은 `close()` 가 처리하지 않은 레코드까지 AUTO 커밋하던 결함을 고쳤습니다.
38
+ 이제 콜백이 정상으로 끝난 레코드만 커밋 대상이고, 콜백하지 못한 레코드는 같은 핸들의 다음 read / listen 이 다시 줍니다.
39
+ - `seek_to_offset(offset, partition)` 이 **다른 파티션**의 받아 두기만 한 레코드와 AUTO 커밋 좌표까지 버리던 결함을
40
+ 고쳤습니다(0.7.2 에도 있었습니다). 엔진은 지정한 파티션만 되감으므로 버려진 다른 파티션 구간은 다시 오지 않았고, AUTO 는
41
+ 뒤 커밋이 그 구간을 건너뛰었습니다. 이제 지정한 파티션만 버리고, seek 응답보다 먼저 도착한(곧 seek 전 위치에서 읽은) 그
42
+ 파티션의 레코드는 앱에 주지 않습니다. `partition` 을 생략하면 엔진은 **0번 파티션 하나만** 되감습니다(`offset=0` 이어도
43
+ 구독 전체가 아닙니다). 예전에는 이때도 모든 파티션의 받아 둔 레코드를 버렸습니다 - 이제 `;partition:0` 을 붙여 보내고 0번
44
+ 것만 버립니다. `seek_to_time()` 은 전 파티션을 되감으므로 전부 버립니다.
45
+ - seek 는 엔진이 멤버를 보지 않고 커서를 옮깁니다. 이 멤버에게 배정된 파티션만 되감고(`get_assignment()`), `seek_to_time()` 은
46
+ 그룹에 멤버가 하나일 때만 쓰세요.
47
+ - `close()` 의 AUTO 커밋이 `MIMQE_TOPIC_REBALANCED (partition N is not owned by this member)` 로 거절되면 그 파티션을 빼고
48
+ 다시 보냅니다 - 아직 소유한 파티션의 좌표는 반영됩니다(예전에는 전부 버려져 다음 멤버에게 다시 갔습니다).
49
+ - **문서**: 세션 목록(`ILSessionProperty`)의 `destroyedTime` 은 살아 있는 세션에서 **-1** 입니다(0 이 아닙니다). 끊긴 세션은
50
+ 끊긴 시각(epoch 밀리초)입니다. 살아 있는지는 `status` 로 판정하세요.
51
+ - **발행 CPU**: `send()` 가 레코드를 배치 버퍼에 곧바로 붙이고, 잠금 / 파티션 선택 / 키 인코딩 비용을 줄였습니다(레코드당 약 30% 감소).
52
+ - **소비 CPU**: 저장 v4 배치 응답을 풀면서 레코드 객체를 바로 만들고, AUTO 커밋 병합을 파티션마다 한 번 합니다(`read_batch` 약 40% 감소).
53
+ - **소비 왕복**:
54
+ - `read()` 가 AUTO / MANUAL 에서 prefetch 건수(기본 500)까지 한 번에 받아 두고 차례로 줍니다(레코드마다 왕복하지 않습니다).
55
+ IMMEDIATE 는 지금처럼 1건씩 요청합니다. 받아 두기만 한 레코드는 커밋되지 않으며, AUTO 커밋은 다음 요청(또는 `close()`)에 실립니다.
56
+ - `commit(list)` / `close()` 가 파티션마다 가장 큰 오프셋을 모아 파티션 수와 관계없이 한 요청으로 커밋합니다.
57
+ - `listen()` 과 prefetch 기본 배치가 100 에서 500 이 됐습니다.
58
+ - **패턴 구독**: `read` / `read_batch` 한 번이 매칭된 토픽 전체를 다중 토픽 read 요청 하나로 묻습니다. 한 토픽이라도 레코드가
59
+ 있으면 곧바로 돌아오고, 모두 비었으면 `timeout_ms` 동안 어느 토픽이든 들어오기를 기다립니다 - 한가한 토픽이 많아도 바쁜 토픽이
60
+ 늦어지지 않습니다. 한 번에 토픽 하나가 가져가는 양은 `bufferPerTopic` 으로 묶고, 시작 토픽을 호출마다 한 칸씩 돌립니다(바쁜
61
+ 토픽이 셋 이상일 때 하나를 건너뛰던 결함을 고쳤습니다). 목록 `commit` 은 토픽마다 한 요청이며, 보내기 전에 전부 검사합니다
62
+ (출처가 없는 레코드가 있으면 아무것도 커밋하지 않습니다).
63
+
64
+ ## 0.7.2 변경 - batchSize 기본값 262144 로 되돌림, 발행 경로 CPU 절감 (자바 v2.3.2 와 같음)
65
+
66
+ - `batchSize` 기본값을 **262144** 로 되돌렸습니다. 0.7.1 의 16384 에서 파이썬 클라는 처리량이 24~35% 낮았습니다(GIL 이
67
+ 천장이라 배치마다 드는 비용이 그대로 처리량에서 빠집니다). 멱등 기본 켜짐은 그대로입니다.
68
+ - 발행 경로 CPU 를 줄였습니다(API 는 그대로입니다). 레코드 future 가 배치 결과 하나를 함께 가리키고(완결은 배치당 한 번),
69
+ 키 -> 파티션 결과를 캐시하고, `send()` 가 설정값을 레코드마다 다시 읽지 않고, I/O 스레드를 깨우는 신호를 합치고,
70
+ ACK 하나의 배치 완결을 잠금 한 번에 묶습니다.
71
+ - producer 는 만들 때 설정 객체를 **복사**합니다(자바 v2.3.2 도 같고, Kafka 와 같습니다). 만든 뒤 넘긴 객체를 바꿔도 그
72
+ producer 에는 반영되지 않습니다 - 설정을 바꾸려면 producer 를 새로 만드십시오.
73
+ - 문서: 멱등이 거르는 것은 producer 안의 재전송뿐입니다 - 앱이 `send` 를 다시 부르면 새 레코드로 적재됩니다.
74
+
11
75
  ## 0.7.1 변경 - producer 기본값: 멱등 켜짐, batchSize 16384 (자바 v2.3.1 과 같음)
12
76
 
13
77
  - `enableIdempotence` 기본값이 **켜짐**입니다. 멱등을 직접 정하지 않았으면 `acks(0)` 이나 `maxInFlight` 가 5 를 넘을 때
@@ -1,6 +1,6 @@
1
1
  """iLink - Python client API for iLink M.O.M. (Message Oriented Middleware)."""
2
2
 
3
- __version__ = "0.7.1"
3
+ __version__ = "0.7.3"
4
4
 
5
5
  # --- Admin / Service ---
6
6
  from .admin import ILAdminService, ILAdminQmgr, ILLogBrowser, ILQueueBrowser
@@ -6,7 +6,7 @@ import time
6
6
  import uuid
7
7
 
8
8
  from .common import ILC, ILRC, MatchOption
9
- from .connectivity import ILRequestHelper
9
+ from .connectivity import ILRequestHelper, _io_lock_of
10
10
  from .exception import (
11
11
  UnsupportedOperationException,
12
12
  ILException,
@@ -5250,7 +5250,6 @@ class ILAdminQmgr:
5250
5250
  str(self.waitMsgTimeoutMS),
5251
5251
  )
5252
5252
  while True:
5253
- self.service.getConn().send(req_msg)
5254
5253
  timeout = self.service.getSessionTimeout()
5255
5254
  if (
5256
5255
  not self.isInfiniteWaiting
@@ -5259,7 +5258,11 @@ class ILAdminQmgr:
5259
5258
  ):
5260
5259
  timeout = self.waitMsgTimeoutMS * 2
5261
5260
 
5262
- msg = self.service.getConn().recv(timeout)
5261
+ # 0.7.3: 요청-응답 짝을 연결 잠금 안에서(무한 대기면 회차마다 놓는다)
5262
+ conn = self.service.getConn()
5263
+ with _io_lock_of(conn):
5264
+ conn.send(req_msg)
5265
+ msg = conn.recv(timeout)
5263
5266
  if msg.getType() == ILC.MIMQ_DATA_MESSAGE:
5264
5267
  return msg.getDataMsg()
5265
5268
 
@@ -260,6 +260,13 @@ class ILC:
260
260
  #: 발행 v2 ACK. corrId + 봉투 code / 사유 + 배치 수 + 배치마다 {partition, code, baseOffset, timestamp,
261
261
  #: expectedSeq, 사유}. 봉투 헤더를 못 읽으면 봉투 code / 사유만 싣고 배치 수 0 이다.
262
262
  MIMQ_TOPIC_PUBLISH_V2_ACK_MESSAGE = 2041
263
+ #: 0.7.3 소비 프로토콜 v5(엔진 CONSV5-1): 요청 태그. 본문 ``[u16 1][i64 corrId]`` - 요청 바로 앞에 보내면 응답 바로 앞에
264
+ #: 같은 태그가 온다(응답 순서는 요청 순서와 다를 수 있다). 큐 PUT/GET, 트랜잭션, 발행에 달면 엔진이 연결을 끊는다.
265
+ MIMQ_REQ_TAG_MESSAGE = 2044
266
+ #: 0.7.3 다중 토픽 read 요청 / 응답(이진 BE). 응답 절 = 토픽, 구독, 상태(0 데이터 / 2 재배정 / 3 오류), 사유, 2042 본문.
267
+ #: 모든 항목이 비어 시간이 다하면 2046 대신 REPORT(``MIMQ_NO_NEW_MESSAGE``)가 온다.
268
+ MIMQ_TOPIC_FETCH_MULTI_MESSAGE = 2045
269
+ MIMQ_TOPIC_FETCH_MULTI_RESP_MESSAGE = 2046
263
270
  MIMQ_LONG_REQUEST_CODE_LENGTH = 6
264
271
  MIMQ_LONG_REQUEST_ARG_LENGTH = 70
265
272
  MIMQ_LIST_ITEM_COUNT_LENGTH = 5