jetstream-api 0.11.0__tar.gz → 0.12.0__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.
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/PKG-INFO +13 -1
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/README.md +12 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/__init__.py +1 -1
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/common.py +7 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/connectivity.py +41 -1
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/qmgr.py +94 -6
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/jetstream_api.egg-info/PKG-INFO +13 -1
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/pyproject.toml +1 -1
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/LICENSE.txt +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/_codec.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/admin.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/admintopic.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/exception.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/msg.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/partitioner.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/pattern.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/producer.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/properties.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/py.typed +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/topic.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/ilink/util.py +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/jetstream_api.egg-info/SOURCES.txt +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/jetstream_api.egg-info/dependency_links.txt +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/jetstream_api.egg-info/requires.txt +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/jetstream_api.egg-info/top_level.txt +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/setup.cfg +0 -0
- {jetstream_api-0.11.0 → jetstream_api-0.12.0}/tests/test_example.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jetstream-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
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,18 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
|
|
|
60
60
|
## 설치 방법
|
|
61
61
|
pip install jetstream-api
|
|
62
62
|
|
|
63
|
+
## 0.12.0 변경 - 큐 전용 요청 코드(엔진 7.0.1.3431 이상) 자동 사용 (자바 v2.8.0 과 같음)
|
|
64
|
+
|
|
65
|
+
- **앱 코드는 바꿀 것이 없습니다.** 엔진 판 줄이 7.x 이고 리비전이 3431 이상이면 클라이언트가 스스로 새 요청 코드를 씁니다.
|
|
66
|
+
그 밖의 엔진(6.3.x, 그보다 앞선 7.x, 5.x)에는 0.11.0 과 같은 요청을 보냅니다.
|
|
67
|
+
- **`commit_and_get`** 은 커밋 요청과 get 요청 대신 전용 요청 하나(COMMIT_AND_GET, 3402)를 보내고 응답도 하나만 받습니다.
|
|
68
|
+
엔진이 커밋한 뒤 곧바로 get 을 돌립니다. 결과와 예외는 0.11.0 과 같습니다.
|
|
69
|
+
- 커밋이 거절되면 get 은 돌지 않았고, 롤백을 보내 커밋하려던 작업과 꺼낸 메시지를 큐에 되돌린 뒤 `ILOperationException` 을 올립니다.
|
|
70
|
+
- 응답을 받기 전에 연결이 끊기면 커밋 결과를 알 수 없습니다(재접속 / 재시도 없음). 커밋 결과가 get 결과와 한 응답으로 오므로
|
|
71
|
+
**결과를 알 수 없는 구간이 get 대기 시간까지** 늘어납니다.
|
|
72
|
+
- **`commit()`** 은 쥐고 있던 트랜잭션 put 이 **하나뿐**이면 put 과 커밋 대신 전용 요청 하나(PUT_AND_COMMIT, 3403)로 보냅니다.
|
|
73
|
+
돌려주는 값과 예외는 같습니다. put 이 둘 이상이거나 `puts`, 64KiB 를 넘는 put, 쥔 것이 없을 때는 0.11.0 과 같습니다.
|
|
74
|
+
|
|
63
75
|
## 0.11.0 변경 - 큐 단건 put / get 가속, `commit_and_get` 추가
|
|
64
76
|
|
|
65
77
|
- **새 API `ILQueue.commit_and_get(matchId=None, option=MatchOption.NONE)`** (camelCase 별칭 `commitAndGet`): 이 세션의
|
|
@@ -10,6 +10,18 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
|
|
|
10
10
|
## 설치 방법
|
|
11
11
|
pip install jetstream-api
|
|
12
12
|
|
|
13
|
+
## 0.12.0 변경 - 큐 전용 요청 코드(엔진 7.0.1.3431 이상) 자동 사용 (자바 v2.8.0 과 같음)
|
|
14
|
+
|
|
15
|
+
- **앱 코드는 바꿀 것이 없습니다.** 엔진 판 줄이 7.x 이고 리비전이 3431 이상이면 클라이언트가 스스로 새 요청 코드를 씁니다.
|
|
16
|
+
그 밖의 엔진(6.3.x, 그보다 앞선 7.x, 5.x)에는 0.11.0 과 같은 요청을 보냅니다.
|
|
17
|
+
- **`commit_and_get`** 은 커밋 요청과 get 요청 대신 전용 요청 하나(COMMIT_AND_GET, 3402)를 보내고 응답도 하나만 받습니다.
|
|
18
|
+
엔진이 커밋한 뒤 곧바로 get 을 돌립니다. 결과와 예외는 0.11.0 과 같습니다.
|
|
19
|
+
- 커밋이 거절되면 get 은 돌지 않았고, 롤백을 보내 커밋하려던 작업과 꺼낸 메시지를 큐에 되돌린 뒤 `ILOperationException` 을 올립니다.
|
|
20
|
+
- 응답을 받기 전에 연결이 끊기면 커밋 결과를 알 수 없습니다(재접속 / 재시도 없음). 커밋 결과가 get 결과와 한 응답으로 오므로
|
|
21
|
+
**결과를 알 수 없는 구간이 get 대기 시간까지** 늘어납니다.
|
|
22
|
+
- **`commit()`** 은 쥐고 있던 트랜잭션 put 이 **하나뿐**이면 put 과 커밋 대신 전용 요청 하나(PUT_AND_COMMIT, 3403)로 보냅니다.
|
|
23
|
+
돌려주는 값과 예외는 같습니다. put 이 둘 이상이거나 `puts`, 64KiB 를 넘는 put, 쥔 것이 없을 때는 0.11.0 과 같습니다.
|
|
24
|
+
|
|
13
25
|
## 0.11.0 변경 - 큐 단건 put / get 가속, `commit_and_get` 추가
|
|
14
26
|
|
|
15
27
|
- **새 API `ILQueue.commit_and_get(matchId=None, option=MatchOption.NONE)`** (camelCase 별칭 `commitAndGet`): 이 세션의
|
|
@@ -467,6 +467,13 @@ class ILC:
|
|
|
467
467
|
#: SUBSCRIPTION_NOT_FOUND, 그 (토픽, 구독)에 read 가 걸려 있으면(태그 롱폴 / FETCH_MULTI 항목) 4157
|
|
468
468
|
#: MIMQE_READ_IN_PROGRESS. 다시 read 하면 다시 든다(재배정 통지부터). r3416 이하 엔진은 모르는 요청으로 거절한다.
|
|
469
469
|
MIMQ_TOPIC_LEAVE = 3401
|
|
470
|
+
#: 0.12.0(엔진 r3431, 사용자 결정 2026-09-15): 큐 전용 요청. 판 줄 major 가 7 이고 리비전이 3431 이상인 엔진에만 보낸다.
|
|
471
|
+
#: 칸은 GET 과 같다(arg2 큐 이름, arg3 대기 ms, 확장 = 선택자). 트랜잭션 세션이면 엔진이 커밋한 뒤 GET 을 돌려 GET 응답
|
|
472
|
+
#: 하나만 준다. 커밋이 실패하면 MIMQ_NOT_SUCCESSFUL_COMMIT 하나만 온다(GET 은 돌지 않았다).
|
|
473
|
+
MIMQ_COMMIT_AND_GET_REQUEST = 3402
|
|
474
|
+
#: 0.12.0(엔진 r3431): 인자 없음, 확장 = DATA 프레임 하나(put 이 보내는 프레임). 응답은 COMMIT 과 같다. commit() 이 쥔 것이
|
|
475
|
+
#: 트랜잭션 put 하나뿐일 때 [PUT + COMMIT] 대신 쓴다.
|
|
476
|
+
MIMQ_PUT_AND_COMMIT_REQUEST = 3403
|
|
470
477
|
|
|
471
478
|
# 토픽 응답 코드
|
|
472
479
|
MIMQ_SUCCESSFUL_TOPIC_OPERATION = 4156
|
|
@@ -506,6 +506,8 @@ class TCPConnector:
|
|
|
506
506
|
# 0.11.0 K2: 응답이 없는 송신(트랜잭션 세션의 put)을 쥐고 있다가 이 연결의 다음 송신과 한 번에 쓴다(send_deferred)
|
|
507
507
|
self._wpend: list = []
|
|
508
508
|
self._wpend_len = 0
|
|
509
|
+
#: 0.12.0: 쥔 첫 프레임이 put(DATA)인가 - _single_pending_put 이 본다(쥔 것이 하나일 때만 뜻이 있다)
|
|
510
|
+
self._wpend_put1 = False
|
|
509
511
|
|
|
510
512
|
def _rx_reset(self) -> None:
|
|
511
513
|
# 받아 둔 바이트와 쥔 송신을 버린다(끊기 / 새 접속). 다음 수신은 timeout 을 다시 준다
|
|
@@ -676,11 +678,20 @@ class TCPConnector:
|
|
|
676
678
|
data = msg.toByteArray(True)
|
|
677
679
|
if (self.socket is not None and self._is_connected() and len(data) <= _WPEND_FRAME_MAX
|
|
678
680
|
and self._wpend_len + len(data) <= _WPEND_TOTAL_MAX):
|
|
681
|
+
# 0.12.0: 쥔 것이 put 프레임 하나뿐인지 본다(commit 이 PUT_AND_COMMIT 로 바꿔 쓸지). 빈 자리에 처음 쥘 때 정한다
|
|
682
|
+
if not self._wpend:
|
|
683
|
+
self._wpend_put1 = msg.getType() == ILC.MIMQ_DATA_MESSAGE
|
|
679
684
|
self._wpend.append(data)
|
|
680
685
|
self._wpend_len += len(data)
|
|
681
686
|
return
|
|
682
687
|
self.send_bytes(data)
|
|
683
688
|
|
|
689
|
+
def _single_pending_put(self) -> bytes | None:
|
|
690
|
+
# 0.12.0: 쥔 것이 put(DATA) 프레임 하나뿐이면 그 프레임(전송 구분자 포함), 아니면 None. 쥔 것은 그대로 둔다(연결 잠금 안에서 부른다)
|
|
691
|
+
if len(self._wpend) == 1 and self._wpend_put1:
|
|
692
|
+
return self._wpend[0]
|
|
693
|
+
return None
|
|
694
|
+
|
|
684
695
|
def _flush_wpend(self, sock) -> None:
|
|
685
696
|
# 쥔 송신을 내보낸다(K2). 실패는 송신 실패와 같은 사유로 올린다 - 부르는 쪽이 연결을 닫는다
|
|
686
697
|
data = b"".join(self._wpend)
|
|
@@ -692,7 +703,9 @@ class TCPConnector:
|
|
|
692
703
|
raise ILSessionException(ILRC.MIMQE_BIO_ERROR, "write() failure.", exc) from exc
|
|
693
704
|
|
|
694
705
|
def _discard_wpend(self) -> None:
|
|
695
|
-
#
|
|
706
|
+
# _request_const(discard_pending=True) 가 부른다 - 지금은 그렇게 부르는 곳이 없다(rollback 도 쥔 put 을 ROLLBACK 과 함께
|
|
707
|
+
# 보내 0.10.0 과 같은 롤백 응답을 받는다). 끊기 / 새 접속 때 비우는 것은 _rx_reset 이다
|
|
708
|
+
# 쥔 put 은 아직 엔진에 가지 않았으므로 버리면 보낸 뒤 롤백한 것과 같다
|
|
696
709
|
self._wpend.clear()
|
|
697
710
|
self._wpend_len = 0
|
|
698
711
|
|
|
@@ -1390,6 +1403,33 @@ class ILRequestHelper:
|
|
|
1390
1403
|
report_msg._arrival = getattr(res_msg, "_arrival", 0)
|
|
1391
1404
|
return report_msg
|
|
1392
1405
|
|
|
1406
|
+
def _request_put_and_commit(self) -> ILReportMsg | None:
|
|
1407
|
+
# 0.12.0: 연결이 쥔 것이 put(DATA) 프레임 하나뿐이면 [PUT + COMMIT] 대신 PUT_AND_COMMIT(3403) 하나로 보내고 응답(COMMIT 과
|
|
1408
|
+
# 같은 보고)을 돌려준다. 쥔 것이 없거나 둘 이상 / 태그 계층 / 라이브러리 커넥터가 아님 / 프레임 상한을 넘음 = None - 부르는
|
|
1409
|
+
# 쪽이 COMMIT 을 보낸다(쥔 것은 그 앞에 붙어 나간다). 엔진 판 확인(7.x 리비전 3431 이상)은 부르는 쪽(ILQmgr.commit)이 한다
|
|
1410
|
+
conn = self.conn
|
|
1411
|
+
if type(conn) is not TCPConnector or self._gate is not None:
|
|
1412
|
+
return None
|
|
1413
|
+
with _io_lock_of(conn):
|
|
1414
|
+
put = conn._single_pending_put()
|
|
1415
|
+
if put is None:
|
|
1416
|
+
return None
|
|
1417
|
+
# 확장 = 쥔 put 프레임에서 끝 전송 구분자를 뺀 것 = to_byte_array(False), PUTS 서브메시지와 같은 형식(엔진 확인 2026-09-15).
|
|
1418
|
+
# 엔진은 확장이 DATA 프레임 하나이고 그 길이 칸 값이 확장 바이트 수와 같은지 본다(구분자가 붙으면 거절 + 롤백)
|
|
1419
|
+
frame = ILMsgUtil.create_request_msg_with_ext(ILC.MIMQ_PUT_AND_COMMIT_REQUEST, bytes(put[:-1])).to_byte_array(True)
|
|
1420
|
+
if len(frame) - 1 > conn.max_frame_length:
|
|
1421
|
+
return None
|
|
1422
|
+
conn._discard_wpend()
|
|
1423
|
+
conn.send_bytes(frame)
|
|
1424
|
+
res_msg = _stamp_arrival(conn.recv(self.sessionTimeoutMS), self._arrivals)
|
|
1425
|
+
if ILC.MIMQ_REPORT_MESSAGE != res_msg.getType():
|
|
1426
|
+
raise ILMsgTypeException(
|
|
1427
|
+
res_msg.getType(), " msg type must be [MIMQ_REPORT_MESSAGE]"
|
|
1428
|
+
)
|
|
1429
|
+
report_msg = res_msg.getReportMsg()
|
|
1430
|
+
report_msg._arrival = getattr(res_msg, "_arrival", 0)
|
|
1431
|
+
return report_msg
|
|
1432
|
+
|
|
1393
1433
|
@contextlib.contextmanager
|
|
1394
1434
|
def _exclusive(self):
|
|
1395
1435
|
# 연결을 다시 붙이는 동안 혼자 쓴다. 진행 중인 호출(걸린 롱폴 포함)이 끝나기를 기다리고 새 호출은 그 뒤에 세운다
|
|
@@ -88,6 +88,27 @@ def _engine_in_order(version: str) -> bool:
|
|
|
88
88
|
return major == 6 and minor == 3 and m.group(3) is not None and int(m.group(3)) >= 3
|
|
89
89
|
|
|
90
90
|
|
|
91
|
+
# 0.12.0: 큐 전용 요청 코드(COMMIT_AND_GET 3402 / PUT_AND_COMMIT 3403)를 아는 엔진인가 - 판 줄 major 가 7 이고 리비전(넷째 칸)이
|
|
92
|
+
# 3431 이상(엔진 r3431, 사용자 결정 2026-09-15). 6.3.x / 옛 7.x / 판을 읽지 못함 = 0.11.0 경로(자바 v2.8.0 과 같다)
|
|
93
|
+
# 네 칸 모두 숫자이고 그 뒤는 공백이나 끝이어야 한다(자바 ILQueue.isQueueFastEngine 과 같은 판정)
|
|
94
|
+
_VERSION_FULL = re.compile(r"\s*([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)(?:\s|$)")
|
|
95
|
+
_QUEUE_FAST_REVISION = 3431
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@functools.lru_cache(maxsize=16)
|
|
99
|
+
def _engine_qfast(version: str) -> bool:
|
|
100
|
+
"""엔진 판 문자열이 큐 전용 요청 코드(3402 / 3403)를 아는 판인지.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
version (str): :meth:`ILQmgr.get_version` 값(예 ``"7.0.1.3431 jetstream"``).
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
bool: 판 줄 major 가 7 이고 리비전(넷째 칸)이 3431 이상이면 True.
|
|
107
|
+
"""
|
|
108
|
+
m = _VERSION_FULL.match(version)
|
|
109
|
+
return m is not None and int(m.group(1)) == 7 and int(m.group(4)) >= _QUEUE_FAST_REVISION
|
|
110
|
+
|
|
111
|
+
|
|
91
112
|
class ILQmgr:
|
|
92
113
|
"""큐 관리자에 붙어 메시지를 넣고 빼는 **응용 클라이언트**.
|
|
93
114
|
|
|
@@ -608,6 +629,9 @@ class ILQmgr:
|
|
|
608
629
|
큐 하나가 아니라 **세션 전체**가 단위다. 여러 큐에 걸친 put/get 이
|
|
609
630
|
한 트랜잭션으로 묶여 원자적으로 확정된다.
|
|
610
631
|
|
|
632
|
+
엔진 7.x 리비전 3431 이상이고, 아직 보내지 않고 쥐고 있던 트랜잭션 put 이 **하나뿐**이면 put 과 커밋 대신
|
|
633
|
+
전용 요청 하나(PUT_AND_COMMIT)로 보낸다(0.12.0). 뜻 · 반환값 · 예외는 같다(앞선 작업이 있으면 함께 확정된다).
|
|
634
|
+
|
|
611
635
|
Example::
|
|
612
636
|
|
|
613
637
|
qmgr.connect("192.168.0.10", 5000, auto_commit=False)
|
|
@@ -618,7 +642,15 @@ class ILQmgr:
|
|
|
618
642
|
"""
|
|
619
643
|
try:
|
|
620
644
|
self.txnPending = False
|
|
621
|
-
report_msg =
|
|
645
|
+
report_msg = None
|
|
646
|
+
# 0.12.0: 쥔 것이 트랜잭션 put 하나뿐이고 엔진이 PUT_AND_COMMIT 를 알면(7.x 리비전 3431 이상) [PUT + COMMIT] 대신 그
|
|
647
|
+
# 요청 하나로 보낸다. 뜻과 응답은 put() + commit() 과 같다(앞선 작업이 있으면 함께 커밋된다, 자바 v2.8.0 과 같다)
|
|
648
|
+
if _engine_qfast(self.get_version() or ""):
|
|
649
|
+
fast = getattr(self.service, "_request_put_and_commit", None)
|
|
650
|
+
if fast is not None:
|
|
651
|
+
report_msg = fast()
|
|
652
|
+
if report_msg is None:
|
|
653
|
+
report_msg = self._request_const(_COMMIT)
|
|
622
654
|
if report_msg is None:
|
|
623
655
|
raise ILOperationException("MIMQE_INTERNAL_ERROR")
|
|
624
656
|
if report_msg.getCode() != ILC.MIMQ_SUCCESSFUL_COMMIT:
|
|
@@ -1627,6 +1659,8 @@ class ILQueue:
|
|
|
1627
1659
|
self.isInfiniteWaiting = False
|
|
1628
1660
|
# 0.11.0 K7: 마지막으로 짠 GET 요청 (대기 시간 문자열, 선택자, 큐 이름, ILMsg, 프레임 바이트)
|
|
1629
1661
|
self._getCache = None
|
|
1662
|
+
# 0.12.0: 마지막으로 짠 COMMIT_AND_GET 프레임 (대기 시간 문자열, 선택자, 큐 이름, 프레임 바이트)
|
|
1663
|
+
self._cagCache = None
|
|
1630
1664
|
|
|
1631
1665
|
if not existCheck:
|
|
1632
1666
|
return
|
|
@@ -2041,17 +2075,19 @@ class ILQueue:
|
|
|
2041
2075
|
ILNoMsgException: 대기 시간(:meth:`set_wait_msg_timeout_ms`, 기본 60초) 안에 메시지가 없을 때.
|
|
2042
2076
|
**이때도 커밋은 이미 성공했다.**
|
|
2043
2077
|
ILOperationException: 커밋이 실패했을 때(:meth:`ILQmgr.commit` 과 같은 예외, 사유는 엔진이 준 값). 이때는
|
|
2044
|
-
|
|
2078
|
+
롤백을 보내 커밋하려던 작업과 꺼낸 메시지를 큐에 되돌린 뒤 올린다. 또는 커밋은 성공했는데 get 을
|
|
2045
2079
|
엔진이 거절했을 때(:meth:`get` 과 같은 예외).
|
|
2046
|
-
ILSessionException: 커밋 요청을 보낸 뒤 커밋
|
|
2080
|
+
ILSessionException: 커밋 요청을 보낸 뒤 커밋 결과를 받기 전에 연결이 끊겼을 때. **커밋 결과를 알 수 없으므로
|
|
2047
2081
|
자동 재접속 / 재시도를 하지 않는다**(:meth:`ILQmgr.commit` 과 같다) - 다시 붙어 트랜잭션을 처음부터 수행한다.
|
|
2082
|
+
전용 요청(아래 Note)이면 커밋 결과가 get 결과와 한 응답으로 오므로 이 구간이 **get 대기 시간까지** 늘어난다.
|
|
2048
2083
|
ILException: 그 밖의 통신 실패.
|
|
2049
2084
|
|
|
2050
2085
|
Note:
|
|
2051
2086
|
* 자동 커밋 세션(``auto_commit=True``)이면 커밋 요청 없이 :meth:`get` 과 똑같이 동작한다.
|
|
2052
|
-
*
|
|
2053
|
-
|
|
2054
|
-
|
|
2087
|
+
* 엔진 7.x 리비전 3431 이상에는 **전용 요청 하나(COMMIT_AND_GET)** 를 보내고 응답도 하나만 받는다(0.12.0 - 엔진이
|
|
2088
|
+
커밋한 뒤 곧바로 get 을 돌린다). 한 세션의 요청을 받은 순서대로 처리하고 그 순서로 답하는 것이 확인된 그 밖의
|
|
2089
|
+
엔진(그보다 앞선 7.x, 6.3.3 이상의 6.3.x)에는 커밋과 get 요청을 연달아 보낸다(와이어 형식은 0.10.0 과 같다). 그 밖의
|
|
2090
|
+
엔진(5.x 등, 판을 읽지 못한 경우 포함)에서는 커밋 응답을 받은 뒤 get 을 보낸다 - 결과는 같고 2 왕복이다.
|
|
2055
2091
|
* 커밋이 성공한 뒤 get 이 통신 장애로 실패하면 :meth:`get` 과 같이 자동 재접속 후 1회 재시도한다(커밋할 것이
|
|
2056
2092
|
이제 없다).
|
|
2057
2093
|
* 무한 대기(``set_wait_msg_timeout_ms(-1)``)면 첫 get 이 비었을 때 :meth:`get` 과 같이 계속 기다린다.
|
|
@@ -2088,12 +2124,64 @@ class ILQueue:
|
|
|
2088
2124
|
# 순서 처리가 확인되지 않은 엔진 / 커밋과 큐가 다른 연결 / 가짜 커넥터: 커밋 응답을 받은 뒤 get(2 왕복, 뜻은 같다)
|
|
2089
2125
|
qm.commit()
|
|
2090
2126
|
return self.get(matchId, option)
|
|
2127
|
+
if _engine_qfast(version):
|
|
2128
|
+
# 0.12.0: 큐 전용 요청 코드를 아는 엔진(7.x, 리비전 3431 이상) - COMMIT_AND_GET 하나를 보내고 응답도 하나를 받는다
|
|
2129
|
+
return self._commit_and_get_code(matchId, option, send_raw)
|
|
2091
2130
|
return self._commit_and_get_pipelined(matchId, option, send_raw, req[1])
|
|
2092
2131
|
|
|
2093
2132
|
def commitAndGet(self, matchId: str | None = None, option: MatchOption = MatchOption.NONE) -> ILDataMsg:
|
|
2094
2133
|
""":meth:`commit_and_get` 의 camelCase 별칭."""
|
|
2095
2134
|
return self.commit_and_get(matchId, option)
|
|
2096
2135
|
|
|
2136
|
+
def _commit_and_get_frame(self, matchId: str | None, option: MatchOption) -> bytes:
|
|
2137
|
+
# 0.12.0: COMMIT_AND_GET 프레임. 칸은 GET 과 같고 코드만 다르다 - GET 캐시와 같은 열쇠(대기 시간 / 선택자 / 큐 이름)로 캐시한다
|
|
2138
|
+
ext = ILC.make_selector(matchId, option).encode("utf-8") if matchId else None
|
|
2139
|
+
wait = str(self.waitMsgTimeoutMS)
|
|
2140
|
+
c = self._cagCache
|
|
2141
|
+
if c is not None and c[0] == wait and c[1] == ext and c[2] == self.name:
|
|
2142
|
+
return c[3]
|
|
2143
|
+
frame = ILMsgUtil.create_request_msg_with_ext(
|
|
2144
|
+
ILC.MIMQ_COMMIT_AND_GET_REQUEST, ext, "", self.name, wait
|
|
2145
|
+
).to_byte_array(True)
|
|
2146
|
+
self._cagCache = (wait, ext, self.name, frame)
|
|
2147
|
+
return frame
|
|
2148
|
+
|
|
2149
|
+
def _commit_and_get_code(self, matchId: str | None, option: MatchOption, send_raw) -> ILDataMsg:
|
|
2150
|
+
# 0.12.0: COMMIT_AND_GET(3402) 하나를 보내고 응답 하나를 읽는다(쥔 put 이 있으면 그 앞에 붙는다). 엔진이 커밋한 뒤 GET 을 돌린다.
|
|
2151
|
+
# 커밋이 실패하면 NOT_SUCCESSFUL_COMMIT 하나만 오고 GET 은 돌지 않았다 - ROLLBACK 을 보내 0.11.0 과 같은 상태로 끝내고 commit() 과
|
|
2152
|
+
# 같은 예외를 낸다. 응답 전에 끊기면 커밋 여부를 모른다 - commit() 처럼 올리고 재시도하지 않는다(모르는 구간이 GET 대기까지
|
|
2153
|
+
# 늘어난다, 자바 v2.8.0 과 같다)
|
|
2154
|
+
qm = self.qmgr
|
|
2155
|
+
conn = self.conn
|
|
2156
|
+
frame = self._commit_and_get_frame(matchId, option)
|
|
2157
|
+
try:
|
|
2158
|
+
with _io_lock_of(conn):
|
|
2159
|
+
qm.txnPending = False
|
|
2160
|
+
qm.set_last_access_time()
|
|
2161
|
+
send_raw(frame)
|
|
2162
|
+
res = conn.recv(self._get_recv_timeout())
|
|
2163
|
+
except _PASSTHROUGH_EXCEPTIONS:
|
|
2164
|
+
raise
|
|
2165
|
+
except Exception as exc:
|
|
2166
|
+
raise ILException(exc) from exc
|
|
2167
|
+
if res.getType() == ILC.MIMQ_REPORT_MESSAGE and res.getReportMsg().getCode() == ILC.MIMQ_NOT_SUCCESSFUL_COMMIT:
|
|
2168
|
+
# 커밋 거절. 엔진은 트랜잭션 오류면 롤백을 마쳤고 클러스터 정지면 트랜잭션을 남긴다 - 0.11.0 과 같은 끝 상태(커밋하려던 작업이
|
|
2169
|
+
# 모두 되돌아감)가 되도록 ROLLBACK 을 보낸다(거절 때만의 왕복 1 번, rollback() 은 예외를 올리지 않는다)
|
|
2170
|
+
qm.rollback()
|
|
2171
|
+
raise ILOperationException(res.getReportMsg().getArg2())
|
|
2172
|
+
# 커밋 확정. 여기부터는 get() 과 같다
|
|
2173
|
+
try:
|
|
2174
|
+
got = self._take_get_reply(res)
|
|
2175
|
+
except _PASSTHROUGH_EXCEPTIONS:
|
|
2176
|
+
raise
|
|
2177
|
+
except Exception as exc:
|
|
2178
|
+
raise ILException(exc) from exc
|
|
2179
|
+
if got is not None:
|
|
2180
|
+
return got
|
|
2181
|
+
if self.isInfiniteWaiting:
|
|
2182
|
+
return self.get(matchId, option) # 무한 대기 - get() 의 반복을 이어 간다
|
|
2183
|
+
raise ILNoMsgException(qm.get_name(), self.name)
|
|
2184
|
+
|
|
2097
2185
|
def _commit_and_get_pipelined(self, matchId: str | None, option: MatchOption, send_raw, frame: bytes) -> ILDataMsg:
|
|
2098
2186
|
# COMMIT + GET 을 sendall 한 번으로 보내고(쥔 put 이 있으면 그 앞에 붙는다) 응답 둘을 차례로 읽는다. 연결 잠금은 교환
|
|
2099
2187
|
# 전체(실패 때의 ROLLBACK 포함) 동안 쥔다. 기록은 commit() + _get_once() 와 같게 - 보낼 때 txnPending 을 끄고,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jetstream-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
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,18 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
|
|
|
60
60
|
## 설치 방법
|
|
61
61
|
pip install jetstream-api
|
|
62
62
|
|
|
63
|
+
## 0.12.0 변경 - 큐 전용 요청 코드(엔진 7.0.1.3431 이상) 자동 사용 (자바 v2.8.0 과 같음)
|
|
64
|
+
|
|
65
|
+
- **앱 코드는 바꿀 것이 없습니다.** 엔진 판 줄이 7.x 이고 리비전이 3431 이상이면 클라이언트가 스스로 새 요청 코드를 씁니다.
|
|
66
|
+
그 밖의 엔진(6.3.x, 그보다 앞선 7.x, 5.x)에는 0.11.0 과 같은 요청을 보냅니다.
|
|
67
|
+
- **`commit_and_get`** 은 커밋 요청과 get 요청 대신 전용 요청 하나(COMMIT_AND_GET, 3402)를 보내고 응답도 하나만 받습니다.
|
|
68
|
+
엔진이 커밋한 뒤 곧바로 get 을 돌립니다. 결과와 예외는 0.11.0 과 같습니다.
|
|
69
|
+
- 커밋이 거절되면 get 은 돌지 않았고, 롤백을 보내 커밋하려던 작업과 꺼낸 메시지를 큐에 되돌린 뒤 `ILOperationException` 을 올립니다.
|
|
70
|
+
- 응답을 받기 전에 연결이 끊기면 커밋 결과를 알 수 없습니다(재접속 / 재시도 없음). 커밋 결과가 get 결과와 한 응답으로 오므로
|
|
71
|
+
**결과를 알 수 없는 구간이 get 대기 시간까지** 늘어납니다.
|
|
72
|
+
- **`commit()`** 은 쥐고 있던 트랜잭션 put 이 **하나뿐**이면 put 과 커밋 대신 전용 요청 하나(PUT_AND_COMMIT, 3403)로 보냅니다.
|
|
73
|
+
돌려주는 값과 예외는 같습니다. put 이 둘 이상이거나 `puts`, 64KiB 를 넘는 put, 쥔 것이 없을 때는 0.11.0 과 같습니다.
|
|
74
|
+
|
|
63
75
|
## 0.11.0 변경 - 큐 단건 put / get 가속, `commit_and_get` 추가
|
|
64
76
|
|
|
65
77
|
- **새 API `ILQueue.commit_and_get(matchId=None, option=MatchOption.NONE)`** (camelCase 별칭 `commitAndGet`): 이 세션의
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|