jetstream-api 0.3.0__tar.gz → 0.4.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.
Files changed (25) hide show
  1. {jetstream_api-0.3.0/jetstream_api.egg-info → jetstream_api-0.4.0}/PKG-INFO +49 -2
  2. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/README.md +48 -1
  3. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/__init__.py +1 -1
  4. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/admin.py +166 -39
  5. jetstream_api-0.4.0/ilink/admintopic.py +617 -0
  6. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/common.py +9 -7
  7. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/connectivity.py +12 -12
  8. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/exception.py +1 -1
  9. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/msg.py +12 -13
  10. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/pattern.py +10 -15
  11. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/producer.py +18 -26
  12. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/properties.py +11 -13
  13. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/qmgr.py +34 -34
  14. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/topic.py +30 -34
  15. {jetstream_api-0.3.0 → jetstream_api-0.4.0/jetstream_api.egg-info}/PKG-INFO +49 -2
  16. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/jetstream_api.egg-info/SOURCES.txt +1 -0
  17. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/pyproject.toml +1 -1
  18. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/LICENSE.txt +0 -0
  19. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/py.typed +0 -0
  20. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/ilink/util.py +0 -0
  21. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/jetstream_api.egg-info/dependency_links.txt +0 -0
  22. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/jetstream_api.egg-info/requires.txt +0 -0
  23. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/jetstream_api.egg-info/top_level.txt +0 -0
  24. {jetstream_api-0.3.0 → jetstream_api-0.4.0}/setup.cfg +0 -0
  25. {jetstream_api-0.3.0 → jetstream_api-0.4.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.0
3
+ Version: 0.4.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
@@ -147,6 +147,53 @@ qmgr.reconnect() # 새 리더를 찾아 재접속
147
147
  > (`reconnect()` 직접 호출은 가능합니다). auto-commit 세션도 응답 유실 시점의 재시도로
148
148
  > **중복 put이 발생할 수 있습니다.**
149
149
 
150
+ ## 0.4.0 신규 - 관리 연결 하나로 pub/sub
151
+
152
+ `ILAdminService`(관리 포트, 보통 9998) 연결만으로 토픽 발행·구독이 가능합니다.
153
+ 큐 관리자 리스너 포트에 따로 붙지 않아도 되므로, **방화벽이 관리 포트만 열린 환경**에서
154
+ 쓸 수 있습니다.
155
+
156
+ > 엔진 v7.0.1 rev 3295 이상이 필요합니다.
157
+
158
+ ```python
159
+ from ilink.admin import ILAdminService
160
+ from ilink.exception import ILNoMsgException
161
+ from ilink.topic import ILSubscribeOptions, ILTopic
162
+
163
+ svc = ILAdminService()
164
+ svc.connect("127.0.0.1", 9998, "admin-app")
165
+ aq = svc.accessAdminQmgr("QM1")
166
+
167
+ # 발행 - (offset, timestamp, partition)
168
+ off, ts, part = aq.publish("ORDER.EVENT", b"payload", key="order-1")
169
+
170
+ # 구독
171
+ topic = aq.accessTopic("ORDER.EVENT")
172
+ sub = topic.subscribe("audit", ILSubscribeOptions()
173
+ .startMode(ILTopic.START_EARLIEST)
174
+ .commitMode(ILTopic.COMMIT_MANUAL))
175
+ try:
176
+ while True:
177
+ try:
178
+ msg = sub.read(3000)
179
+ except ILNoMsgException:
180
+ break
181
+ print(msg.get_offset(), msg.get_key(), msg.get_data_string())
182
+ sub.commit(msg)
183
+ finally:
184
+ sub.close()
185
+ ```
186
+
187
+ 패턴(와일드카드) 구독도 같은 연결로 됩니다.
188
+
189
+ ```python
190
+ ps = aq.accessPattern("ORDER.*").subscribe("audit")
191
+ ```
192
+
193
+ > **제약**: 관리 연결에는 배치가 없어 **레코드 한 건에 한 번 왕복**합니다. 멱등 발행도
194
+ > 지원되지 않습니다(acks=1 고정). 대량 처리나 중복 제거가 필요하면 리스너 포트에
195
+ > `ILQmgr` 로 붙어 `ILTopicProducer` 를 쓰세요.
196
+
150
197
  ## 0.3.0 신규 - 허브-스포크 연결 전환 헬퍼
151
198
 
152
199
  허브에 접속해 스포크를 찾고 연결을 전환하는 세 단계를 한 번에 처리하는
@@ -218,7 +265,7 @@ sub = topic.assign("app1", [0, 2], ILTopic.START_EARLIEST) # 수동 파티션
218
265
 
219
266
  ## 개발자 가이드 문서
220
267
 
221
- **공개 API 756개 전부에 한국어 docstring이 붙어 있습니다.** 편집기에서 함수 위에
268
+ **공개 API 779개 전부에 한국어 docstring이 붙어 있습니다.** 편집기에서 함수 위에
222
269
  마우스를 올리거나 `help()`로 파라미터 타입·기본값·허용값·예외를 바로 확인할 수 있습니다.
223
270
 
224
271
  ```python
@@ -101,6 +101,53 @@ qmgr.reconnect() # 새 리더를 찾아 재접속
101
101
  > (`reconnect()` 직접 호출은 가능합니다). auto-commit 세션도 응답 유실 시점의 재시도로
102
102
  > **중복 put이 발생할 수 있습니다.**
103
103
 
104
+ ## 0.4.0 신규 - 관리 연결 하나로 pub/sub
105
+
106
+ `ILAdminService`(관리 포트, 보통 9998) 연결만으로 토픽 발행·구독이 가능합니다.
107
+ 큐 관리자 리스너 포트에 따로 붙지 않아도 되므로, **방화벽이 관리 포트만 열린 환경**에서
108
+ 쓸 수 있습니다.
109
+
110
+ > 엔진 v7.0.1 rev 3295 이상이 필요합니다.
111
+
112
+ ```python
113
+ from ilink.admin import ILAdminService
114
+ from ilink.exception import ILNoMsgException
115
+ from ilink.topic import ILSubscribeOptions, ILTopic
116
+
117
+ svc = ILAdminService()
118
+ svc.connect("127.0.0.1", 9998, "admin-app")
119
+ aq = svc.accessAdminQmgr("QM1")
120
+
121
+ # 발행 - (offset, timestamp, partition)
122
+ off, ts, part = aq.publish("ORDER.EVENT", b"payload", key="order-1")
123
+
124
+ # 구독
125
+ topic = aq.accessTopic("ORDER.EVENT")
126
+ sub = topic.subscribe("audit", ILSubscribeOptions()
127
+ .startMode(ILTopic.START_EARLIEST)
128
+ .commitMode(ILTopic.COMMIT_MANUAL))
129
+ try:
130
+ while True:
131
+ try:
132
+ msg = sub.read(3000)
133
+ except ILNoMsgException:
134
+ break
135
+ print(msg.get_offset(), msg.get_key(), msg.get_data_string())
136
+ sub.commit(msg)
137
+ finally:
138
+ sub.close()
139
+ ```
140
+
141
+ 패턴(와일드카드) 구독도 같은 연결로 됩니다.
142
+
143
+ ```python
144
+ ps = aq.accessPattern("ORDER.*").subscribe("audit")
145
+ ```
146
+
147
+ > **제약**: 관리 연결에는 배치가 없어 **레코드 한 건에 한 번 왕복**합니다. 멱등 발행도
148
+ > 지원되지 않습니다(acks=1 고정). 대량 처리나 중복 제거가 필요하면 리스너 포트에
149
+ > `ILQmgr` 로 붙어 `ILTopicProducer` 를 쓰세요.
150
+
104
151
  ## 0.3.0 신규 - 허브-스포크 연결 전환 헬퍼
105
152
 
106
153
  허브에 접속해 스포크를 찾고 연결을 전환하는 세 단계를 한 번에 처리하는
@@ -172,7 +219,7 @@ sub = topic.assign("app1", [0, 2], ILTopic.START_EARLIEST) # 수동 파티션
172
219
 
173
220
  ## 개발자 가이드 문서
174
221
 
175
- **공개 API 756개 전부에 한국어 docstring이 붙어 있습니다.** 편집기에서 함수 위에
222
+ **공개 API 779개 전부에 한국어 docstring이 붙어 있습니다.** 편집기에서 함수 위에
176
223
  마우스를 올리거나 `help()`로 파라미터 타입·기본값·허용값·예외를 바로 확인할 수 있습니다.
177
224
 
178
225
  ```python
@@ -1,6 +1,6 @@
1
1
  """iLink - Python client API for iLink M.O.M. (Message Oriented Middleware)."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.4.0"
4
4
 
5
5
  # --- Admin / Service ---
6
6
  from .admin import ILAdminService, ILAdminQmgr, ILLogBrowser, ILQueueBrowser
@@ -1154,7 +1154,7 @@ class ILAdminService:
1154
1154
 
1155
1155
  Warning:
1156
1156
  **세션 회수는 비동기다.** 클라이언트가 :meth:`disconnect` 로 정상 종료해도
1157
- 그 세션이 목록에서 곧바로 사라지지 않는다 - 실측(10.10.1.95 허브) 약 **1초**
1157
+ 그 세션이 목록에서 곧바로 사라지지 않는다 - 실측(127.0.0.1 허브) 약 **1초**
1158
1158
  동안 ``getStatus()`` 가 여전히 ``1``, ``getDestroyedTime()`` 이 ``-1`` 인
1159
1159
  채로 남아 있다가 사라진다. 끊긴 것을 확인하려면 **한 번 조회로 단정하지 말고
1160
1160
  잠시 기다렸다 다시 조회하라.**
@@ -1459,13 +1459,13 @@ class ILAdminService:
1459
1459
  조회하거나 지울 수 없다는 뜻이다.
1460
1460
 
1461
1461
  Note:
1462
- 실측(10.10.1.95 허브, 스포크 2대): 전환 자체는 **20~45ms**, 전환 뒤 요청의
1462
+ 실측(127.0.0.1 허브, 스포크 2대): 전환 자체는 **20~45ms**, 전환 뒤 요청의
1463
1463
  릴레이 오버헤드는 **측정되지 않는 수준**이다(``getQmgrList`` 중앙값 릴레이
1464
1464
  18.3ms vs 허브 직결 18.4ms). ``timeoutSec`` 은 0 이나 1 을 줘도 성공했다.
1465
1465
 
1466
1466
  Example::
1467
1467
 
1468
- svc.connect("10.10.1.95", 9998, "ADMIN")
1468
+ svc.connect("127.0.0.1", 9998, "ADMIN")
1469
1469
  for sp in svc.getSpokeList():
1470
1470
  if sp.getName() == "S48":
1471
1471
  svc.spokeSwitchTo(sp.getKey(), 10)
@@ -1509,8 +1509,7 @@ class ILAdminService:
1509
1509
 
1510
1510
  Raises:
1511
1511
  ILOperationException: 그런 이름의 스포크가 없거나 전환이 거절됐을 때.
1512
- 없는 이름이면 ``MIMQE_OBJECT_NOT_FOUND (spoke: 이름)`` 이다 -
1513
- Java 와 사유 코드를 맞추려고 엔진 관례의 접두사를 쓴다.
1512
+ 없는 이름이면 ``MIMQE_OBJECT_NOT_FOUND (spoke: 이름)`` 이다.
1514
1513
  ILSessionException: 허브에 접속하지 못했을 때.
1515
1514
  ILException: 그 밖의 통신 실패.
1516
1515
 
@@ -1525,7 +1524,7 @@ class ILAdminService:
1525
1524
  Example::
1526
1525
 
1527
1526
  for name in ("S48", "S85"):
1528
- svc = ILAdminService.connectToSpoke("10.10.1.95", 9998, "ADMIN", name)
1527
+ svc = ILAdminService.connectToSpoke("127.0.0.1", 9998, "ADMIN", name)
1529
1528
  try:
1530
1529
  print(name, [q.getName() for q in svc.getQmgrList()])
1531
1530
  finally:
@@ -2116,12 +2115,9 @@ class ILAdminQmgr:
2116
2115
  **트레이스를 켜면 로그가 급격히 늘어난다** - 장애 분석 때만 쓰라.
2117
2116
  특정 세션만 보려면 :meth:`setSessionTrace` 가 부담이 적다.
2118
2117
 
2119
- .. warning:: Java 와 의도적으로 다르다
2120
-
2121
- Java 는 성공 코드 자리에 ``MIMQ_NOT_SUCCESSFUL_*`` 을 넘겨 **판정이
2122
- 뒤집혀 있다** - 성공하면 빈 사유로 예외가 나고, 실패하면 조용히 통과한다.
2123
- 파이썬은 ``MIMQ_SUCCESSFUL_*`` 로 바로잡았다(실서버 확인: 성공 4208 /
2124
- 실패 4209). **Java 쪽도 고쳐야 한다.**
2118
+ Note:
2119
+ 성공 판정은 ``MIMQ_SUCCESSFUL_*`` 응답으로 한다(실서버 확인: 성공 4208 /
2120
+ 실패 4209).
2125
2121
  """
2126
2122
  try:
2127
2123
  self.service.request(
@@ -2249,12 +2245,9 @@ class ILAdminQmgr:
2249
2245
  Note:
2250
2246
  큐 관리자 전체(:meth:`setSystemTrace`)보다 로그 부담이 훨씬 적다.
2251
2247
 
2252
- .. warning:: Java 와 의도적으로 다르다
2253
-
2254
- Java 는 성공 코드 자리에 ``MIMQ_NOT_SUCCESSFUL_*`` 을 넘겨 **판정이
2255
- 뒤집혀 있다** - 성공하면 빈 사유로 예외가 나고, 실패하면 조용히 통과한다.
2256
- 파이썬은 ``MIMQ_SUCCESSFUL_*`` 로 바로잡았다(실서버 확인: 성공 4208 /
2257
- 실패 4209). **Java 쪽도 고쳐야 한다.**
2248
+ Note:
2249
+ 성공 판정은 ``MIMQ_SUCCESSFUL_*`` 응답으로 한다(실서버 확인: 성공 4208 /
2250
+ 실패 4209).
2258
2251
  """
2259
2252
  try:
2260
2253
  self.service.request(
@@ -2940,12 +2933,9 @@ class ILAdminQmgr:
2940
2933
  p.setTraceEnabled(True)
2941
2934
  qmgr.setQueueProperty(p)
2942
2935
 
2943
- .. warning:: Java 와 의도적으로 다르다
2944
-
2945
- Java 는 성공 코드 자리에 ``MIMQ_NOT_SUCCESSFUL_*`` 을 넘겨 **판정이
2946
- 뒤집혀 있다** - 성공하면 빈 사유로 예외가 나고, 실패하면 조용히 통과한다.
2947
- 파이썬은 ``MIMQ_SUCCESSFUL_*`` 로 바로잡았다(실서버 확인: 성공 4208 /
2948
- 실패 4209). **Java 쪽도 고쳐야 한다.**
2936
+ Note:
2937
+ 성공 판정은 ``MIMQ_SUCCESSFUL_*`` 응답으로 한다(실서버 확인: 성공 4208 /
2938
+ 실패 4209).
2949
2939
  """
2950
2940
  try:
2951
2941
  self.service.request(
@@ -3803,12 +3793,9 @@ class ILAdminQmgr:
3803
3793
  Note:
3804
3794
  채널이 붙지 않거나 자꾸 끊길 때 원인을 보는 데 쓴다.
3805
3795
 
3806
- .. warning:: Java 와 의도적으로 다르다
3807
-
3808
- Java 는 성공 코드 자리에 ``MIMQ_NOT_SUCCESSFUL_*`` 을 넘겨 **판정이
3809
- 뒤집혀 있다** - 성공하면 빈 사유로 예외가 나고, 실패하면 조용히 통과한다.
3810
- 파이썬은 ``MIMQ_SUCCESSFUL_*`` 로 바로잡았다(실서버 확인: 성공 4208 /
3811
- 실패 4209). **Java 쪽도 고쳐야 한다.**
3796
+ Note:
3797
+ 성공 판정은 ``MIMQ_SUCCESSFUL_*`` 응답으로 한다(실서버 확인: 성공 4208 /
3798
+ 실패 4209).
3812
3799
  """
3813
3800
  try:
3814
3801
  self.service.request(
@@ -3836,12 +3823,9 @@ class ILAdminQmgr:
3836
3823
  ILOperationException: 그런 채널이 없거나 서버가 거절했을 때.
3837
3824
  ILException: 통신 실패.
3838
3825
 
3839
- .. warning:: Java 와 의도적으로 다르다
3840
-
3841
- Java 는 성공 코드 자리에 ``MIMQ_NOT_SUCCESSFUL_*`` 을 넘겨 **판정이
3842
- 뒤집혀 있다** - 성공하면 빈 사유로 예외가 나고, 실패하면 조용히 통과한다.
3843
- 파이썬은 ``MIMQ_SUCCESSFUL_*`` 로 바로잡았다(실서버 확인: 성공 4208 /
3844
- 실패 4209). **Java 쪽도 고쳐야 한다.**
3826
+ Note:
3827
+ 성공 판정은 ``MIMQ_SUCCESSFUL_*`` 응답으로 한다(실서버 확인: 성공 4208 /
3828
+ 실패 4209).
3845
3829
  """
3846
3830
  try:
3847
3831
  self.service.request(
@@ -4261,9 +4245,7 @@ class ILAdminQmgr:
4261
4245
  **토픽을 보려면 반드시 ``objectType`` 을 지정하라.**
4262
4246
 
4263
4247
  Note:
4264
- 자바 API 는 ``createObjectLogBrowser(objectType, objectName)`` 순서지만,
4265
- 여기서는 기존 호출부(``createObjectLogBrowser("TEST.LQ")``)를 깨지 않으려고
4266
- **이름을 먼저** 받는다.
4248
+ 인자 순서는 **이름이 먼저**다 - ``createObjectLogBrowser("TEST.LQ")``.
4267
4249
 
4268
4250
  Example::
4269
4251
 
@@ -5057,6 +5039,151 @@ class ILAdminQmgr:
5057
5039
  except Exception as exc:
5058
5040
  raise ILException(exc) from exc
5059
5041
 
5042
+ # ── 관리 연결 pub/sub (엔진 rev 3295+) ─────────────────────────────
5043
+ def _relayTopic(self, code: int, ext, *args):
5044
+ """토픽 요청을 큐 관리자로 릴레이한다(내부용).
5045
+
5046
+ 관리 연결은 요청에 **대상 큐 관리자 이름**을 실어야 ilsvc 가 릴레이한다.
5047
+ """
5048
+ return self.service.inquire_data_or_report(self.qmgrName, code, ext, *args)
5049
+
5050
+ def get_qmgr_name(self) -> str:
5051
+ """이 핸들이 다루는 큐 관리자 이름.
5052
+
5053
+ Returns:
5054
+ str: 큐 관리자 이름.
5055
+ """
5056
+ return self.qmgrName
5057
+
5058
+ def list_topic_names(self) -> list[str]:
5059
+ """토픽 이름만 뽑아 목록으로 돌려준다.
5060
+
5061
+ Returns:
5062
+ list[str]: 토픽 이름 목록. 없으면 빈 목록.
5063
+
5064
+ Raises:
5065
+ ILOperationException: 서버가 조회를 거절했을 때.
5066
+ ILException: 통신 실패.
5067
+
5068
+ Note:
5069
+ :meth:`getTopicList` 가 돌려주는 ``|`` 구분 원문에서 첫 필드만 모은 것이다.
5070
+ 오프셋이나 파티션 수까지 필요하면 :meth:`getTopicList` 를 쓰라.
5071
+ """
5072
+ raw = self.getTopicList() or ""
5073
+ return [ln.split("|", 1)[0] for ln in raw.split("\n") if ln.strip()]
5074
+
5075
+ def accessTopic(self, topicName: str, existCheck: bool = True) -> "ILAdminTopic":
5076
+ """**관리 연결로** 다룰 토픽 핸들을 얻는다.
5077
+
5078
+ 큐 관리자 리스너 포트에 따로 붙지 않고 관리 포트 연결을 그대로 쓴다.
5079
+ 방화벽이 관리 포트만 열린 환경에서 발행/구독을 할 때 쓴다.
5080
+
5081
+ Args:
5082
+ topicName (str): 토픽 이름.
5083
+ existCheck (bool): True(기본)면 토픽이 있는지 먼저 확인한다.
5084
+
5085
+ Returns:
5086
+ ILAdminTopic: 발행과 구독을 함께 하는 토픽 핸들.
5087
+
5088
+ Raises:
5089
+ ILOperationException: ``existCheck=True`` 인데 토픽이 없을 때.
5090
+ ILException: 통신 실패.
5091
+
5092
+ Warning:
5093
+ 관리 연결에는 **배치가 없다.** 레코드 한 건에 한 번 왕복하므로 대량
5094
+ 소비/발행에는 맞지 않는다. 처리량이 필요하면 리스너 포트에
5095
+ :class:`~ilink.qmgr.ILQmgr` 로 붙으라.
5096
+
5097
+ Note:
5098
+ 엔진 **rev 3295 이상**이 필요하다.
5099
+
5100
+ Example::
5101
+
5102
+ aq = svc.accessAdminQmgr("QM1")
5103
+ topic = aq.accessTopic("ORDER.EVENT")
5104
+
5105
+ off, ts, part = topic.publish(b"payload", key="k1")
5106
+
5107
+ sub = topic.subscribe("audit")
5108
+ try:
5109
+ msg = sub.read(3000)
5110
+ print(msg.get_offset(), msg.get_data_string())
5111
+ sub.commit(msg)
5112
+ finally:
5113
+ sub.close()
5114
+ """
5115
+ from .admintopic import ILAdminTopic
5116
+ return ILAdminTopic(self, topicName, existCheck)
5117
+
5118
+ def accessPattern(self, pattern: str):
5119
+ """**관리 연결로** 다룰 토픽 패턴 핸들을 얻는다.
5120
+
5121
+ Args:
5122
+ pattern (str): 글롭 패턴(예 ``"ORDER.*"``). ``*`` 는 0자 이상으로
5123
+ 구분자 ``.`` 도 삼키고, ``?`` 는 1자다. 비우면 거부한다.
5124
+
5125
+ Returns:
5126
+ ILTopicPattern: 패턴 핸들. **이 시점에는 서버와 통신하지 않는다.**
5127
+
5128
+ Raises:
5129
+ ILOperationException: 패턴이 비었을 때.
5130
+
5131
+ Warning:
5132
+ 관리 연결에는 배치 read 가 없어, 패턴 구독도 하위 토픽을 **한 건씩**
5133
+ 훑는다. 매칭 토픽이 많으면 왕복 수가 그만큼 늘어난다.
5134
+
5135
+ Example::
5136
+
5137
+ pat = aq.accessPattern("ORDER.*")
5138
+ print(pat.resolve()) # 구독 전 오타 확인
5139
+
5140
+ ps = pat.subscribe("audit")
5141
+ try:
5142
+ for msg in ps.read_batch(10, 3000):
5143
+ print(msg.get_topic_name(), msg.get_offset())
5144
+ ps.commit_sync()
5145
+ finally:
5146
+ ps.close()
5147
+ """
5148
+ from .pattern import ILTopicPattern
5149
+ return ILTopicPattern(self, pattern)
5150
+
5151
+ def publish(self, topicName: str, value: bytes, key: str = "",
5152
+ partition: int | None = None) -> tuple[int, int, int]:
5153
+ """관리 연결로 레코드 **한 건**을 발행한다.
5154
+
5155
+ :meth:`accessTopic` 없이 바로 한 건 보낼 때 쓰는 지름길이다.
5156
+
5157
+ Args:
5158
+ topicName (str): 대상 토픽 이름.
5159
+ value (bytes): payload. 빈 값도 허용한다(컴팩션 tombstone).
5160
+ key (str): 파티션 라우팅 키. **UTF-8 69바이트 이하.** 비우면 서버가 고른다.
5161
+ partition (int | None): 파티션 직접 지정. None(기본)이면 서버가 정한다.
5162
+
5163
+ Returns:
5164
+ tuple[int, int, int]: ``(offset, timestamp, partition)``.
5165
+ timestamp 는 epoch 밀리초.
5166
+
5167
+ Raises:
5168
+ ILOperationException: 토픽이 없거나 키가 69바이트를 넘거나 서버가 거절했을 때.
5169
+ ILException: 통신 실패.
5170
+
5171
+ Warning:
5172
+ **멱등 발행이 아니다.** 재시도하면 중복이 생길 수 있다.
5173
+
5174
+ Note:
5175
+ 엔진 **rev 3295 이상**이 필요하다.
5176
+
5177
+ Example::
5178
+
5179
+ off, ts, part = aq.publish("ORDER.EVENT", b"payload", key="k1")
5180
+ """
5181
+ return self.accessTopic(topicName, False).publish(value, key, partition)
5182
+
5183
+ access_topic = accessTopic
5184
+ access_pattern = accessPattern
5185
+ getQmgrName = get_qmgr_name
5186
+
5060
5187
  # snake_case 별칭 (이 패키지 관례 - 두 표기를 모두 제공한다)
5061
5188
  def create_topic(self, topic_name: str, options: str = "") -> None:
5062
5189
  """:meth:`createTopic` 의 snake 별칭."""