jetstream-api 0.4.1__tar.gz → 0.4.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 (25) hide show
  1. {jetstream_api-0.4.1/jetstream_api.egg-info → jetstream_api-0.4.3}/PKG-INFO +1 -1
  2. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/__init__.py +3 -1
  3. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/admin.py +223 -12
  4. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/common.py +1045 -1039
  5. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/properties.py +123 -9
  6. {jetstream_api-0.4.1 → jetstream_api-0.4.3/jetstream_api.egg-info}/PKG-INFO +1 -1
  7. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/pyproject.toml +1 -1
  8. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/LICENSE.txt +0 -0
  9. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/README.md +0 -0
  10. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/admintopic.py +0 -0
  11. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/connectivity.py +0 -0
  12. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/exception.py +0 -0
  13. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/msg.py +0 -0
  14. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/pattern.py +0 -0
  15. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/producer.py +0 -0
  16. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/py.typed +0 -0
  17. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/qmgr.py +0 -0
  18. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/topic.py +0 -0
  19. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/ilink/util.py +0 -0
  20. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/jetstream_api.egg-info/SOURCES.txt +0 -0
  21. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/jetstream_api.egg-info/dependency_links.txt +0 -0
  22. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/jetstream_api.egg-info/requires.txt +0 -0
  23. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/jetstream_api.egg-info/top_level.txt +0 -0
  24. {jetstream_api-0.4.1 → jetstream_api-0.4.3}/setup.cfg +0 -0
  25. {jetstream_api-0.4.1 → jetstream_api-0.4.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.4.1
3
+ Version: 0.4.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
@@ -1,6 +1,6 @@
1
1
  """iLink - Python client API for iLink M.O.M. (Message Oriented Middleware)."""
2
2
 
3
- __version__ = "0.4.1"
3
+ __version__ = "0.4.3"
4
4
 
5
5
  # --- Admin / Service ---
6
6
  from .admin import ILAdminService, ILAdminQmgr, ILLogBrowser, ILQueueBrowser
@@ -26,6 +26,7 @@ from .properties import (
26
26
  ILChannelSecurity,
27
27
  ILChannelBalanceMode,
28
28
  ILClusterNode,
29
+ ILClusterControlResult,
29
30
  ILClusterProperty,
30
31
  ILQmgrProperty,
31
32
  ILSessionProperty,
@@ -75,6 +76,7 @@ __all__ = [
75
76
  "ILChannelSecurity",
76
77
  "ILChannelBalanceMode",
77
78
  "ILClusterNode",
79
+ "ILClusterControlResult",
78
80
  "ILClusterProperty",
79
81
  "ILQmgrProperty",
80
82
  "ILSessionProperty",
@@ -22,6 +22,7 @@ from .properties import (
22
22
  ILChannelStatus,
23
23
  ILChannelType,
24
24
  ILChannelDirection,
25
+ ILClusterControlResult,
25
26
  ILClusterNode,
26
27
  ILClusterProperty,
27
28
  ILQmgrMinorProperty,
@@ -704,9 +705,11 @@ class ILAdminService:
704
705
 
705
706
  Raises:
706
707
  ILOperationException: 세 서비스 주소나 세 ilcc 포트 중 하나라도 비었을 때
707
- (``MIMQE_INVALID_ARGUMENT``), 같은 이름이 이미 있을 때, 이름에 금지
708
- 문자가 있을 때(``MIMQE_UNAVAILABLE_CLUSTER_NAME``), 포트가 1025~65535
709
- 밖일 때(``MIMQE_UNAVAILABLE_PORT_NUMBER``).
708
+ (``MIMQE_INVALID_ARGUMENT``), **세 서비스 주소 중 둘 이상이 같은
709
+ 서비스를 가리킬 때**(``MIMQE_INVALID_ARGUMENT``, 엔진 rev 3322+),
710
+ 같은 이름이 이미 있을 때, 이름에 금지 문자가 있을 때
711
+ (``MIMQE_UNAVAILABLE_CLUSTER_NAME``), 포트가 1025~65535 밖일 때
712
+ (``MIMQE_UNAVAILABLE_PORT_NUMBER``).
710
713
  ILException: 통신 실패.
711
714
 
712
715
  Note:
@@ -721,6 +724,26 @@ class ILAdminService:
721
724
  역할(코디네이터/심판)과 각 ilcc 포트는 **서비스가 배정한다.** 이 호출을
722
725
  받은 서비스가 세 곳에 정의를 퍼뜨리면서 대상별로 채워 넣는다.
723
726
 
727
+ .. warning:: 접속 정보가 겹치면 생성이 실패한다
728
+
729
+ ``priSvc`` / ``secSvc`` / ``witSvc`` 는 **서로 다른 관리 서비스**여야 한다.
730
+ 둘 이상이 같은 서비스를 가리키면 서버가 ``MIMQE_INVALID_ARGUMENT`` 로
731
+ **생성을 거부한다**(엔진 rev 3322+).
732
+
733
+ **같은 IP 라도 관리 서비스 포트가 다르면 된다**(한 호스트에 여러 서비스를
734
+ 띄우는 시험 구성이 그렇다). 비교는 ``"호스트:포트"`` 로 하며 포트를 생략하면
735
+ 9998 로 본다 - 즉 ``"10.0.0.1"`` 과 ``"10.0.0.1:9998"`` 은 같은 주소이고,
736
+ ``"10.0.0.1:9988"`` 은 다른 주소다.
737
+
738
+ 왜 막느냐면, 겹친 채로 만들어지면 그 서비스가 같은 이름의 오브젝트를 두
739
+ 역할로 갖게 되고 전파가 "있으면 갱신"으로 처리해 **나중 것이 앞 것을
740
+ 덮어쓰기** 때문이다. 조정자가 하나뿐인 구성 - 3-서비스를 강제해서 막으려던
741
+ 바로 그 상태가 된다.
742
+
743
+ **rev 3322 미만 엔진은 검사하지 않는다.** 거부 없이 그 구성이 그대로
744
+ 만들어지므로 부르는 쪽이 지켜야 한다. 이 라이브러리는 검사하지 않는다 -
745
+ 판정을 두 곳에 두면 규칙이 어긋나기 때문이다.
746
+
724
747
  Warning:
725
748
  **닿지 않는 서비스가 있어도 이 호출은 성공한다.** 구성만 미리 해두는
726
749
  운영을 허용하기 때문이다. 대신 클러스터가 ``STARTING`` 에 머물고
@@ -867,6 +890,34 @@ class ILAdminService:
867
890
  노드 편집은 **읽고-고치고-쓴다**: getClusterProperty 로 받아
868
891
  add_node()/remove_node() 한 뒤 이 메서드로 되돌려준다.
869
892
 
893
+ Raises:
894
+ ILOperationException: 노드가 규칙을 어겼을 때(전부
895
+ ``MIMQE_INVALID_ARGUMENT``) - 큐 관리자 이름이 빈 노드가 있을 때
896
+ (**rev 3319+**), 같은 ``host:port`` 노드가 둘 이상일 때, 같은
897
+ ``nodeId`` 노드가 둘 이상일 때(**rev 3323+**).
898
+ ILException: 통신 실패.
899
+
900
+ .. warning:: 토폴로지는 여기서 바꾸지 마라
901
+
902
+ ``priSvc`` / ``secSvc`` / ``witSvc`` 와 세 포트는 **생성 시점에 정하는
903
+ 값**이다. ilsc 의 ALTER 는 이 항목을 아예 받지 않는다. 그런데 이 메서드는
904
+ 속성 전체를 통째로 보내므로 **바뀐 채로 저장된다**(실측).
905
+
906
+ 문제는 **빠진 서비스에 오브젝트가 남는다**는 것이다. 전파는 새 토폴로지로만
907
+ 가므로 옛 서비스는 통지를 못 받고, 그 자리에 **옛 토폴로지를 든 오브젝트가
908
+ 그대로 남는다**(실측: SEC 을 옮긴 뒤 옛 SEC 서비스에 잔존). 조정자를
909
+ 옮기려면 **클러스터를 지우고 다시 만들어라.**
910
+
911
+ Note:
912
+ **클러스터 구성 검사는 전부 이 경로에서 이뤄진다.** 노드 추가/삭제도
913
+ 결국 여기로 오므로, 서버는 쓰기 입구인 여기 한 곳에서 막는다.
914
+ :meth:`addClusterNode` / :meth:`removeClusterNode` 도 같은 검사를 받는다.
915
+
916
+ 중복 노드가 왜 막히는지는
917
+ :meth:`ILClusterProperty.add_node` 를 보라 - 요약하면 같은 큐 관리자를
918
+ 두 노드로 등록하면 이중 제어가 되고, ``nodeId`` 가 겹치면 **노드가 서로
919
+ 다른 id 를 받아 갈라진다.**
920
+
870
921
  Example::
871
922
 
872
923
  p = svc.getClusterProperty("CC1")
@@ -895,7 +946,11 @@ class ILAdminService:
895
946
  port (int): **큐 관리자 리스너 포트**(ilcc 포트가 아니다).
896
947
 
897
948
  Raises:
898
- ILOperationException: 조회나 반영이 거절됐을 때.
949
+ ILOperationException: 조회나 반영이 거절됐을 때. **같은 ``host:port``
950
+ 노드가 이미 있으면 거절된다** - 한 큐 관리자를 두 노드로 등록하는
951
+ 셈이기 때문이다(``MIMQE_ALREADY_EXIST`` 로 이 라이브러리가 먼저 막고,
952
+ 블롭을 직접 만들어 보내도 서버가 ``MIMQE_INVALID_ARGUMENT`` 로
953
+ 거절한다 - **엔진 rev 3323+**).
899
954
  ILException: 통신 실패.
900
955
 
901
956
  Warning:
@@ -946,26 +1001,165 @@ class ILAdminService:
946
1001
  self.setClusterProperty(vo)
947
1002
  return True
948
1003
 
949
- def startCluster(self, clusterName: str) -> None:
950
- """ilcc 프로세스를 기동한다. 이미 떠 있으면 실패한다."""
1004
+ def _clusterNodesArg(self, withNodes: bool) -> str:
1005
+ """START/STOP CLUSTER 의 arg3 를 만든다.
1006
+
1007
+ Args:
1008
+ withNodes (bool): 엮인 큐 관리자까지 제어할지.
1009
+
1010
+ Returns:
1011
+ str: 기본이면 ``""``, 조정자만 다루면 ``"N"``.
1012
+
1013
+ Raises:
1014
+ ILOperationException: ``withNodes=False`` 인데 엔진이 **rev 3315 미만**일 때.
1015
+
1016
+ Note:
1017
+ 구엔진은 이 인자를 **조용히 무시하고 큐 관리자까지 내린다.** 침묵하는
1018
+ 옵션은 "안 내린다"고 믿게 만들어 옵션이 없는 것보다 나쁘므로, 보내기 전에
1019
+ 막는다. 판정을 ``0 < revision`` 으로 한정한 이유는 버전 문자열을 파싱하지
1020
+ 못했을 때 정상 엔진에서 기능이 조용히 사라지지 않게 하기 위해서다.
1021
+ """
1022
+ if withNodes:
1023
+ return ""
1024
+ if 0 < self.revision < ILC.CLUSTER_NO_NODES_MIN_REVISION:
1025
+ raise ILOperationException(
1026
+ "MIMQE_NOT_SUPPORTED (withNodes=False requires engine rev "
1027
+ f"{ILC.CLUSTER_NO_NODES_MIN_REVISION}+, current: {self.revision})"
1028
+ )
1029
+ return ILC.MIMQ_CLUSTER_NO_NODES
1030
+
1031
+ def startCluster(self, clusterName: str,
1032
+ withNodes: bool = True) -> "ILClusterControlResult":
1033
+ """클러스터를 기동한다 - 기본은 **ilcc 와 엮인 큐 관리자를 함께** 올린다.
1034
+
1035
+ Args:
1036
+ clusterName (str): 기동할 클러스터 이름.
1037
+ withNodes (bool): 엮인 큐 관리자까지 함께 기동할지. 기본 True.
1038
+ ``False`` 면 조정자(ilcc)만 올리고 데이터 평면은 건드리지 않는다.
1039
+ **엔진 rev 3315 이상**에서만 쓸 수 있다.
1040
+
1041
+ Returns:
1042
+ ILClusterControlResult: 제어된 노드 수와 **빠진 노드 목록**.
1043
+ ``getSkipped()`` 이 0 이 아니면 일부 노드가 처리되지 않은 것이다.
1044
+ 엔진 rev 3317 미만은 집계를 싣지 않으므로 ``known`` 이 False 로 온다.
1045
+
1046
+ Raises:
1047
+ ILOperationException: 이미 떠 있을 때(``MIMQE_CLUSTER_NOT_STOPPED``),
1048
+ 그런 클러스터가 없을 때, ``withNodes=False`` 인데 엔진이 rev 3315
1049
+ 미만일 때(``MIMQE_NOT_SUPPORTED``).
1050
+ ILException: 통신 실패.
1051
+
1052
+ Warning:
1053
+ **기본값은 조정자만 올리는 게 아니다.** 노드 목록에 있는 큐 관리자 중
1054
+ **이 서비스 소관인 것**을 함께 기동한다(엔진 rev 3309+). 다른 서비스
1055
+ 소관 노드는 전파받은 그쪽 서비스가 올린다. "클러스터를 켠다 = 데이터
1056
+ 평면까지 켠다"는 뜻이라 그렇다.
1057
+
1058
+ .. warning:: 성공 반환이 "전부 떴다"는 뜻이 아니다
1059
+
1060
+ 노드 제어는 **최선 노력**이라 일부가 빠져도 이 호출은 성공을 돌려준다.
1061
+ 빠진 노드는 반환값 :class:`ILClusterControlResult` 로 알려 주므로
1062
+ **반드시 확인하라**(엔진 rev 3317+). 빠지는 경우는 이렇다.
1063
+
1064
+ - 개별 노드 제어가 실패했다(그 서비스가 로그를 남기고 다음 노드로 넘어간다).
1065
+ - 다른 서비스 소관 노드인데 **전파가 닿지 못했다.** 그쪽 노드는 그대로 남는다.
1066
+
1067
+ 큐 관리자 이름이 빈 노드도 제어 대상에서 빠지는데, 엔진 **rev 3319 부터
1068
+ 그런 노드는 애초에 저장이 거부**되므로 새로 만든 클러스터에서는 생기지
1069
+ 않는다. rev 3319 이전에 등록된 레거시 노드가 남아 있다면
1070
+ :meth:`removeClusterNode` 후 :meth:`addClusterNode` 로 이름을 채워야 한다.
1071
+
1072
+ ::
1073
+
1074
+ r = svc.startCluster("CC1")
1075
+ if r.getSkipped():
1076
+ print("제어 대상에서 빠진 노드:", r.getSkippedNodes())
1077
+ print("제어한 노드 %d개" % r.getControlled())
1078
+
1079
+ Note:
1080
+ 요청만 보내고 돌아온다. 상태는 :meth:`getClusterProperty` 로 확인하라.
1081
+
1082
+ Example::
1083
+
1084
+ svc.startCluster("CC1") # 큐 관리자까지 함께
1085
+ svc.startCluster("CC1", withNodes=False) # 조정자(ilcc)만
1086
+
1087
+ for _ in range(30):
1088
+ if svc.getClusterProperty("CC1").get_status_string() == "RUNNING":
1089
+ break
1090
+ time.sleep(0.5)
1091
+ """
951
1092
  try:
952
1093
  self._checkClusterSupported()
953
- self.service.request(
1094
+ res = self.service.request(
954
1095
  ILC.MIMQ_START_CLUSTER,
955
- ILC.MIMQ_SUCCESSFUL_CLUSTER_OPERATION,
956
1096
  clusterName,
1097
+ "",
1098
+ self._clusterNodesArg(withNodes),
957
1099
  )
1100
+ if res is None or res.getCode() != ILC.MIMQ_SUCCESSFUL_CLUSTER_OPERATION:
1101
+ raise ILOperationException(
1102
+ res.getArg1() if res is not None else "no response")
1103
+ return ILClusterControlResult(res.getArg1(), res.getArg2(), res.getArg3())
958
1104
  except _PASSTHROUGH_EXCEPTIONS:
959
1105
  raise
960
1106
  except Exception as exc:
961
1107
  raise ILException(exc) from exc
962
1108
 
963
- def stopCluster(self, clusterName: str) -> None:
964
- """ilcc 프로세스를 정지한다.
1109
+ def stopCluster(self, clusterName: str,
1110
+ withNodes: bool = True) -> "ILClusterControlResult":
1111
+ """클러스터를 정지한다 - 기본은 **ilcc 와 엮인 큐 관리자를 함께** 내린다.
1112
+
1113
+ Args:
1114
+ clusterName (str): 정지할 클러스터 이름.
1115
+ withNodes (bool): 엮인 큐 관리자까지 함께 정지할지. 기본 True.
1116
+ ``False`` 면 조정자(ilcc)만 내리고 **데이터 평면은 살려 둔다.**
1117
+ **엔진 rev 3315 이상**에서만 쓸 수 있다.
1118
+
1119
+ Returns:
1120
+ ILClusterControlResult: 제어된 노드 수와 **빠진 노드 목록**.
1121
+ ``getSkipped()`` 이 0 이 아니면 일부 노드가 처리되지 않은 것이다.
1122
+ 엔진 rev 3317 미만은 집계를 싣지 않으므로 ``known`` 이 False 로 온다.
1123
+
1124
+ Raises:
1125
+ ILOperationException: ``withNodes=False`` 인데 엔진이 rev 3315 미만일 때
1126
+ (``MIMQE_NOT_SUPPORTED``).
1127
+ ILException: 통신 실패.
965
1128
 
966
1129
  미기동 상태에서 호출해도 성공이다(큐관리자 STOP 관례와 같다).
967
1130
  정지 후에는 서비스 자동 기동 대상에서도 빠진다 - startCluster 로 되살린다.
968
1131
 
1132
+ .. warning:: 기본값은 큐 관리자까지 내린다
1133
+
1134
+ 노드 목록에 있는 큐 관리자 중 **이 서비스 소관인 것**을 함께 정지시킨다
1135
+ (엔진 rev 3309+). 그 위에서 돌던 응용의 연결이 함께 끊어진다.
1136
+ 조정자만 내리고 데이터 평면을 살려 두려면 ``withNodes=False`` 를 쓴다.
1137
+
1138
+ **구엔진(rev 3315 미만)은 이 옵션을 조용히 무시하고 큐 관리자까지
1139
+ 내린다.** 그래서 이 라이브러리가 보내기 전에 막는다 - 안 내려갈 것이라
1140
+ 믿고 부르는 것이 가장 위험하기 때문이다.
1141
+
1142
+ .. warning:: 성공 반환이 "전부 내려갔다"는 뜻이 아니다
1143
+
1144
+ 노드 제어는 **최선 노력**이라 일부가 빠져도 이 호출은 성공을 돌려준다.
1145
+ 빠진 노드는 반환값 :class:`ILClusterControlResult` 로 알려 주므로
1146
+ **반드시 확인하라**(엔진 rev 3317+). 빠지는 경우는 이렇다.
1147
+
1148
+ - 개별 노드 제어가 실패했다(그 서비스가 로그를 남기고 다음 노드로 넘어간다).
1149
+ - 다른 서비스 소관 노드인데 **전파가 닿지 못했다.** 그쪽 노드는 그대로 남는다.
1150
+
1151
+ 큐 관리자 이름이 빈 노드도 제어 대상에서 빠지는데, 엔진 **rev 3319 부터
1152
+ 그런 노드는 애초에 저장이 거부**되므로 새로 만든 클러스터에서는 생기지
1153
+ 않는다. rev 3319 이전에 등록된 레거시 노드가 남아 있다면
1154
+ :meth:`removeClusterNode` 후 :meth:`addClusterNode` 로 이름을 채워야 한다.
1155
+
1156
+ ::
1157
+
1158
+ r = svc.stopCluster("CC1")
1159
+ if r.getSkipped():
1160
+ print("제어 대상에서 빠진 노드:", r.getSkippedNodes())
1161
+ print("제어한 노드 %d개" % r.getControlled())
1162
+
969
1163
  .. warning:: 정지 완료를 기다리지 않는다
970
1164
 
971
1165
  요청만 보내고 바로 돌아온다. **곧바로** :meth:`removeCluster` 를 부르면
@@ -973,14 +1167,31 @@ class ILAdminService:
973
1167
  :meth:`getClusterProperty` 의 상태가 ``STOPPED`` 가 될 때까지 확인하고
974
1168
  진행하라 - 큐관리자와 달리 ``stopClusterWithStatus`` 같은 대기형 메서드가
975
1169
  없다.
1170
+
1171
+ Example::
1172
+
1173
+ # 조정자만 내린다 - 큐 관리자는 계속 서비스한다 (ilcc 패치 등)
1174
+ svc.stopCluster("CC1", withNodes=False)
1175
+ svc.startCluster("CC1", withNodes=False)
1176
+
1177
+ # 클러스터를 통째로 내린다 (기본)
1178
+ svc.stopCluster("CC1")
1179
+ while svc.getClusterProperty("CC1").get_status_string() != "STOPPED":
1180
+ time.sleep(0.5)
1181
+ svc.removeCluster("CC1")
976
1182
  """
977
1183
  try:
978
1184
  self._checkClusterSupported()
979
- self.service.request(
1185
+ res = self.service.request(
980
1186
  ILC.MIMQ_STOP_CLUSTER,
981
- ILC.MIMQ_SUCCESSFUL_CLUSTER_OPERATION,
982
1187
  clusterName,
1188
+ "",
1189
+ self._clusterNodesArg(withNodes),
983
1190
  )
1191
+ if res is None or res.getCode() != ILC.MIMQ_SUCCESSFUL_CLUSTER_OPERATION:
1192
+ raise ILOperationException(
1193
+ res.getArg1() if res is not None else "no response")
1194
+ return ILClusterControlResult(res.getArg1(), res.getArg2(), res.getArg3())
984
1195
  except _PASSTHROUGH_EXCEPTIONS:
985
1196
  raise
986
1197
  except Exception as exc: