huaweicloud-encryption-sdk-python 1.2.1__py3-none-any.whl

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 (174) hide show
  1. examples/file_encryption_example.py +57 -0
  2. examples/key_capsule_encryption_example.py +240 -0
  3. examples/kms_discovery_encryption_example.py +56 -0
  4. examples/local_aes_encryption_example.py +59 -0
  5. examples/test_rsa.py +42 -0
  6. examples/test_sm2.py +38 -0
  7. examples/test_sm4_cbc.py +37 -0
  8. examples/test_sm4_gcm.py +37 -0
  9. huaweicloud_encryption_sdk_python-1.2.1.dist-info/METADATA +18 -0
  10. huaweicloud_encryption_sdk_python-1.2.1.dist-info/RECORD +174 -0
  11. huaweicloud_encryption_sdk_python-1.2.1.dist-info/WHEEL +5 -0
  12. huaweicloud_encryption_sdk_python-1.2.1.dist-info/top_level.txt +3 -0
  13. huaweicloud_encryptionsdk/__init__.py +5 -0
  14. huaweicloud_encryptionsdk/_apig_sdk/__init__.py +1 -0
  15. huaweicloud_encryptionsdk/_apig_sdk/signer.py +278 -0
  16. huaweicloud_encryptionsdk/_apig_sdk/signer_v11.py +70 -0
  17. huaweicloud_encryptionsdk/_apig_sdk/sm3_hash.py +141 -0
  18. huaweicloud_encryptionsdk/_lts_sdk/auth/__init__.py +0 -0
  19. huaweicloud_encryptionsdk/_lts_sdk/auth/signer.py +174 -0
  20. huaweicloud_encryptionsdk/_lts_sdk/consumer/__init__.py +0 -0
  21. huaweicloud_encryptionsdk/_lts_sdk/consumer/client/__init__.py +0 -0
  22. huaweicloud_encryptionsdk/_lts_sdk/consumer/client/consumer_client_adapter.py +59 -0
  23. huaweicloud_encryptionsdk/_lts_sdk/consumer/client/http_client.py +211 -0
  24. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/__init__.py +0 -0
  25. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/client_consumer_worker.py +106 -0
  26. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/consumer_heartbeat.py +73 -0
  27. huaweicloud_encryptionsdk/_lts_sdk/consumer/core/log_shard_consumer.py +179 -0
  28. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/__init__.py +0 -0
  29. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_check_point_tracker.py +120 -0
  30. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor.py +18 -0
  31. huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor_factory.py +3 -0
  32. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/__init__.py +0 -0
  33. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/check_point.py +20 -0
  34. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/consumer_config.py +27 -0
  35. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/log_data.py +18 -0
  36. huaweicloud_encryptionsdk/_lts_sdk/consumer/model/task_result.py +40 -0
  37. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/__init__.py +0 -0
  38. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/consumer_fetch_task.py +53 -0
  39. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/initial_task.py +55 -0
  40. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/process_task.py +25 -0
  41. huaweicloud_encryptionsdk/_lts_sdk/consumer/task/shutdown_task.py +24 -0
  42. huaweicloud_encryptionsdk/_lts_sdk/consumer_main.py +88 -0
  43. huaweicloud_encryptionsdk/_lts_sdk/parallel_main.py +64 -0
  44. huaweicloud_encryptionsdk/_lts_sdk/producer/__init__.py +0 -0
  45. huaweicloud_encryptionsdk/_lts_sdk/producer/callback/__init__.py +0 -0
  46. huaweicloud_encryptionsdk/_lts_sdk/producer/callback/call_back.py +7 -0
  47. huaweicloud_encryptionsdk/_lts_sdk/producer/core/__init__.py +0 -0
  48. huaweicloud_encryptionsdk/_lts_sdk/producer/core/accumulator.py +135 -0
  49. huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_thread_pool.py +107 -0
  50. huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_worker.py +124 -0
  51. huaweicloud_encryptionsdk/_lts_sdk/producer/core/mover.py +69 -0
  52. huaweicloud_encryptionsdk/_lts_sdk/producer/core/producer.py +98 -0
  53. huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/__init__.py +0 -0
  54. huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/http_client.py +63 -0
  55. huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/simple_request.py +14 -0
  56. huaweicloud_encryptionsdk/_lts_sdk/producer/model/__init__.py +0 -0
  57. huaweicloud_encryptionsdk/_lts_sdk/producer/model/config.py +50 -0
  58. huaweicloud_encryptionsdk/_lts_sdk/producer/model/error.py +18 -0
  59. huaweicloud_encryptionsdk/_lts_sdk/producer/model/log.py +87 -0
  60. huaweicloud_encryptionsdk/_lts_sdk/producer/model/log_batch.py +154 -0
  61. huaweicloud_encryptionsdk/_lts_sdk/producer/model/lts_store.py +21 -0
  62. huaweicloud_encryptionsdk/_lts_sdk/producer/model/result.py +17 -0
  63. huaweicloud_encryptionsdk/_lts_sdk/producer/model/retry_queue.py +39 -0
  64. huaweicloud_encryptionsdk/_lts_sdk/serial_main.py +77 -0
  65. huaweicloud_encryptionsdk/_lts_sdk/utils/__init__.py +0 -0
  66. huaweicloud_encryptionsdk/_lts_sdk/utils/common.py +57 -0
  67. huaweicloud_encryptionsdk/_lts_sdk/utils/lts_threading.py +32 -0
  68. huaweicloud_encryptionsdk/cache/__init__.py +0 -0
  69. huaweicloud_encryptionsdk/cache/data_key_cache.py +79 -0
  70. huaweicloud_encryptionsdk/cache/local_data_key_cache.py +161 -0
  71. huaweicloud_encryptionsdk/common/__init__.py +0 -0
  72. huaweicloud_encryptionsdk/common/constants.py +15 -0
  73. huaweicloud_encryptionsdk/common/counting_output_stream.py +18 -0
  74. huaweicloud_encryptionsdk/common/crypto_factory.py +48 -0
  75. huaweicloud_encryptionsdk/common/ec_private_key_loader.py +43 -0
  76. huaweicloud_encryptionsdk/common/ecs_metadata_service.py +42 -0
  77. huaweicloud_encryptionsdk/common/file_path_for_example_constants.py +4 -0
  78. huaweicloud_encryptionsdk/common/utils.py +162 -0
  79. huaweicloud_encryptionsdk/exception/__init__.py +0 -0
  80. huaweicloud_encryptionsdk/exception/errors.py +109 -0
  81. huaweicloud_encryptionsdk/handler/__init__.py +0 -0
  82. huaweicloud_encryptionsdk/handler/cipher_handler.py +294 -0
  83. huaweicloud_encryptionsdk/handler/crypto_handler.py +24 -0
  84. huaweicloud_encryptionsdk/handler/default_crypto_handler.py +148 -0
  85. huaweicloud_encryptionsdk/handler/default_serialize_handler.py +45 -0
  86. huaweicloud_encryptionsdk/handler/file_decrypt_handler.py +101 -0
  87. huaweicloud_encryptionsdk/handler/file_encrypt_handler.py +30 -0
  88. huaweicloud_encryptionsdk/handler/serialize_handler.py +14 -0
  89. huaweicloud_encryptionsdk/huawei_config.py +49 -0
  90. huaweicloud_encryptionsdk/huawei_crypto.py +311 -0
  91. huaweicloud_encryptionsdk/keyrings/__init__.py +0 -0
  92. huaweicloud_encryptionsdk/keyrings/keyring.py +14 -0
  93. huaweicloud_encryptionsdk/keyrings/keyring_factory.py +10 -0
  94. huaweicloud_encryptionsdk/keyrings/kms_keyring_factory.py +21 -0
  95. huaweicloud_encryptionsdk/keyrings/kmskeyring/__init__.py +0 -0
  96. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_discovery_keyring.py +51 -0
  97. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_key_capsule_keyring.py +100 -0
  98. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_keyring.py +155 -0
  99. huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_multi_region_keyring.py +8 -0
  100. huaweicloud_encryptionsdk/keyrings/raw_keyring_factory.py +27 -0
  101. huaweicloud_encryptionsdk/keyrings/rawkeyring/__init__.py +0 -0
  102. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_aes_keyring.py +63 -0
  103. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_keyring.py +112 -0
  104. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_rsa_keyring.py +55 -0
  105. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm2_keyring.py +75 -0
  106. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_cbc_keyring.py +66 -0
  107. huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_keyring.py +70 -0
  108. huaweicloud_encryptionsdk/kms/__init__.py +0 -0
  109. huaweicloud_encryptionsdk/kms/create_key_capsule_request.py +35 -0
  110. huaweicloud_encryptionsdk/kms/create_key_capsule_response.py +19 -0
  111. huaweicloud_encryptionsdk/kms/decrypt_key_capsule_request.py +32 -0
  112. huaweicloud_encryptionsdk/kms/decrypt_key_capsule_response.py +19 -0
  113. huaweicloud_encryptionsdk/kms/kms_http_client.py +116 -0
  114. huaweicloud_encryptionsdk/log/__init__.py +0 -0
  115. huaweicloud_encryptionsdk/log/log_config.py +30 -0
  116. huaweicloud_encryptionsdk/log/log_file_backup.py +144 -0
  117. huaweicloud_encryptionsdk/log/log_metrics.py +132 -0
  118. huaweicloud_encryptionsdk/log/log_reporter_manager.py +163 -0
  119. huaweicloud_encryptionsdk/log/lts_sdk_producer.py +386 -0
  120. huaweicloud_encryptionsdk/log/lts_struct_log_builder.py +106 -0
  121. huaweicloud_encryptionsdk/meterialmanager/__init__.py +0 -0
  122. huaweicloud_encryptionsdk/meterialmanager/cache_crypto_meterial_manager.py +221 -0
  123. huaweicloud_encryptionsdk/meterialmanager/crypto_meterial_manager.py +19 -0
  124. huaweicloud_encryptionsdk/meterialmanager/data_key_generate.py +10 -0
  125. huaweicloud_encryptionsdk/meterialmanager/data_key_generate_factory.py +20 -0
  126. huaweicloud_encryptionsdk/meterialmanager/default_crypto_meterials_manager.py +71 -0
  127. huaweicloud_encryptionsdk/meterialmanager/key_capsule_data_key_generate.py +63 -0
  128. huaweicloud_encryptionsdk/meterialmanager/kms_data_key_generate.py +65 -0
  129. huaweicloud_encryptionsdk/meterialmanager/local_data_key_generate.py +13 -0
  130. huaweicloud_encryptionsdk/model/__init__.py +0 -0
  131. huaweicloud_encryptionsdk/model/access_point_config.py +9 -0
  132. huaweicloud_encryptionsdk/model/cipher_body.py +81 -0
  133. huaweicloud_encryptionsdk/model/cipher_header.py +405 -0
  134. huaweicloud_encryptionsdk/model/ciphertext_data_key.py +166 -0
  135. huaweicloud_encryptionsdk/model/crypto_result.py +11 -0
  136. huaweicloud_encryptionsdk/model/data_key_materials.py +17 -0
  137. huaweicloud_encryptionsdk/model/data_materials.py +11 -0
  138. huaweicloud_encryptionsdk/model/enums/__init__.py +0 -0
  139. huaweicloud_encryptionsdk/model/enums/access_point_type.py +28 -0
  140. huaweicloud_encryptionsdk/model/enums/crypto_algorithm.py +75 -0
  141. huaweicloud_encryptionsdk/model/enums/data_key_generate_type.py +20 -0
  142. huaweicloud_encryptionsdk/model/enums/key_provider_enum.py +19 -0
  143. huaweicloud_encryptionsdk/model/enums/keyring_type_enum.py +27 -0
  144. huaweicloud_encryptionsdk/model/key_capsule.py +10 -0
  145. huaweicloud_encryptionsdk/model/key_capsule_config.py +12 -0
  146. huaweicloud_encryptionsdk/model/kms_config.py +10 -0
  147. huaweicloud_encryptionsdk/model/request/__init__.py +0 -0
  148. huaweicloud_encryptionsdk/model/request/encrypt_request.py +10 -0
  149. huaweicloud_encryptionsdk/model/request/sign_request.py +2 -0
  150. huaweicloud_encryptionsdk/model/request/verify_request.py +2 -0
  151. huaweicloud_encryptionsdk/proof/__init__.py +0 -0
  152. huaweicloud_encryptionsdk/proof/attestation_document.py +36 -0
  153. huaweicloud_encryptionsdk/proof/collector/__init__.py +0 -0
  154. huaweicloud_encryptionsdk/proof/collector/cce_proof_collector.py +24 -0
  155. huaweicloud_encryptionsdk/proof/collector/ecs_proof_collector.py +11 -0
  156. huaweicloud_encryptionsdk/proof/collector/key_pair_proof_collector.py +55 -0
  157. huaweicloud_encryptionsdk/proof/collector/ma_proof_collector.py +51 -0
  158. huaweicloud_encryptionsdk/proof/private_key_decrypt_callback.py +7 -0
  159. huaweicloud_encryptionsdk/proof/proof_collector.py +11 -0
  160. huaweicloud_encryptionsdk/proof/proof_collector_factory.py +53 -0
  161. huaweicloud_encryptionsdk/proof/proof_info.py +10 -0
  162. huaweicloud_encryptionsdk/util/__init__.py +0 -0
  163. huaweicloud_encryptionsdk/util/common_utils.py +12 -0
  164. tests/__init__.py +0 -0
  165. tests/test_enums.py +84 -0
  166. tests/test_exceptions.py +38 -0
  167. tests/test_factories.py +71 -0
  168. tests/test_huawei_crypto.py +67 -0
  169. tests/test_imports.py +46 -0
  170. tests/test_kms_models.py +95 -0
  171. tests/test_log_file_backup.py +45 -0
  172. tests/test_lts_struct_log_builder.py +97 -0
  173. tests/test_models.py +142 -0
  174. tests/test_utils.py +111 -0
@@ -0,0 +1,106 @@
1
+ import threading
2
+ import time
3
+ from concurrent.futures import ThreadPoolExecutor
4
+
5
+ from loguru import logger
6
+
7
+ from consumer.client.consumer_client_adapter import LogConsumerClientAdapter
8
+ from consumer.core.consumer_heartbeat import LogConsumerHeartBeat
9
+ from consumer.core.log_shard_consumer import LogShardConsumer
10
+ from consumer.interface.consumer_processor_factory import ILogConsumerProcessorFactory
11
+ from consumer.model.consumer_config import ConsumerConfig
12
+
13
+
14
+ class ClientConsumerWorker(threading.Thread):
15
+ def __init__(self, processor_factory: ILogConsumerProcessorFactory, config: ConsumerConfig):
16
+ super().__init__()
17
+ self.processor_factory = processor_factory
18
+ self.config = config
19
+ self.executor = ThreadPoolExecutor(max_workers=2, thread_name_prefix="huawei-log-pool-")
20
+ self.shard_consumer = {}
21
+ self.client_adapter = LogConsumerClientAdapter(config)
22
+ self.heart_beat = LogConsumerHeartBeat(self.client_adapter, config)
23
+ self.shut_down = False
24
+ self.main_loop_exit = False
25
+
26
+ def check_consumer_group_exist(self):
27
+ err, check_point = self.client_adapter.fetch_consumer_group("")
28
+ return err
29
+
30
+ def run(self):
31
+ self.heart_beat.start()
32
+ while True:
33
+ if not self.shut_down:
34
+ self.heart_beat.lock.acquire_write()
35
+ for shard in self.heart_beat.current_held_shards:
36
+ consumer = self.consumer_for_shard(shard)
37
+ consumer.consume()
38
+
39
+ self.clean_consumer(self.heart_beat.current_held_shards)
40
+ self.heart_beat.lock.release_write()
41
+ time.sleep(self.config.fetch_interval_mill / 1000)
42
+ else:
43
+ break
44
+ self.main_loop_exit = True
45
+
46
+ def consumer_for_shard(self, shard_id):
47
+ if shard_id in self.shard_consumer:
48
+ return self.shard_consumer[shard_id]
49
+ return self.get_log_shard_consumer(shard_id)
50
+
51
+ def get_log_shard_consumer(self, shard_id):
52
+ consumer = LogShardConsumer(self.client_adapter, shard_id, self.processor_factory.generate_processor(),
53
+ self.config, self.heart_beat)
54
+ self.shard_consumer[shard_id] = consumer
55
+ logger.info("create a consumer for shard: {}", shard_id)
56
+ return consumer
57
+
58
+ def clean_consumer(self, owned_shard):
59
+ shard_to_unload = {}
60
+ for shard, consumer in self.shard_consumer.items():
61
+ if shard in owned_shard:
62
+ if consumer.is_shutdown():
63
+ consumer = LogShardConsumer(self.client_adapter, shard,
64
+ self.processor_factory.generate_processor(),
65
+ self.config, self.heart_beat)
66
+ logger.info("create a consumer for shard: {}", shard)
67
+ self.shard_consumer[shard] = consumer
68
+ continue
69
+ # logger.info("shutting down consumer of shard: {}", shard)
70
+ # consumer.shutdown()
71
+ if consumer.is_shutdown():
72
+ shard_to_unload[shard] = consumer
73
+ logger.info("shard shutdown done, removing from heartbeat list: {}", shard)
74
+
75
+ for shard, consumer in shard_to_unload.items():
76
+ self.shard_consumer.pop(shard)
77
+
78
+ for shard, consumer in owned_shard.items():
79
+ if shard not in self.shard_consumer:
80
+ shard_to_unload[shard] = consumer
81
+
82
+ if len(shard_to_unload) > 0:
83
+ self.heart_beat.unsubscribe(shard_to_unload)
84
+ logger.warning("cancel heart beating for {}", shard_to_unload)
85
+
86
+ def shutdown(self):
87
+ self.shut_down = True
88
+ times = 0
89
+ while not self.main_loop_exit and times < 20:
90
+ times += 1
91
+ time.sleep(1)
92
+
93
+ for key, consumer in self.shard_consumer:
94
+ consumer.shutdown()
95
+
96
+ self.heart_beat.stop()
97
+ self.client_adapter.shutdown()
98
+
99
+
100
+ def get_client_consumer_worker(processor_factory: ILogConsumerProcessorFactory, config: ConsumerConfig):
101
+ worker = ClientConsumerWorker(processor_factory, config)
102
+ err = worker.check_consumer_group_exist()
103
+ if err is not None:
104
+ logger.error("get client consumer work error {}", err.error_msg)
105
+ return None
106
+ return worker
@@ -0,0 +1,73 @@
1
+ import threading
2
+ from concurrent.futures import ThreadPoolExecutor
3
+
4
+ from loguru import logger
5
+
6
+ from consumer.client.consumer_client_adapter import LogConsumerClientAdapter
7
+ from consumer.model.consumer_config import ConsumerConfig
8
+ from huaweicloud_encryptionsdk._lts_sdk.utils import common, lts_threading
9
+
10
+
11
+ class LogConsumerHeartBeat(threading.Thread):
12
+ def __init__(self, client_adapter: LogConsumerClientAdapter, config: ConsumerConfig):
13
+ super().__init__()
14
+ self._client_adapter = client_adapter
15
+ self._heartbeat_interval_mill = config.heartbeat_interval_mill
16
+ self._timeout_sec = config.timeout_sec
17
+ self._current_held_shards = {}
18
+ self._all_heart_shards = {}
19
+ self._last_success_time = 0
20
+ self._is_stop = False
21
+ self._lock = lts_threading.ReadWriteLock()
22
+ self._thread_pool = ThreadPoolExecutor(max_workers=10240, thread_name_prefix="io_thread_pool_sender")
23
+
24
+ @property
25
+ def lock(self):
26
+ return self._lock
27
+
28
+ @property
29
+ def current_held_shards(self):
30
+ return self._current_held_shards
31
+
32
+ @current_held_shards.setter
33
+ def current_held_shards(self, value: int):
34
+ self._current_held_shards = value
35
+
36
+ def run(self):
37
+ while True:
38
+ if self._is_stop:
39
+ return
40
+ err, shards = self._client_adapter.hear_beat(_convert_all_heart_shards(self._all_heart_shards))
41
+ if err is not None:
42
+ now = common.current_time_ms()
43
+ if now - self._last_success_time > self._timeout_sec * 1000 + self._heartbeat_interval_mill:
44
+ self._current_held_shards = {}
45
+ else:
46
+ self._current_held_shards = {}
47
+ self._lock.acquire_write()
48
+ for shard in shards:
49
+ self._current_held_shards[shard] = ""
50
+ self._all_heart_shards[shard] = ""
51
+ self._lock.release_write()
52
+ self._last_success_time = common.current_time_ms()
53
+ logger.debug(
54
+ "after heart beat, current_held_shards is {}, all_heart_shards is {}, last_success_time is {}",
55
+ self._current_held_shards, self._all_heart_shards, self._last_success_time)
56
+ common.sleep_ms(self._heartbeat_interval_mill)
57
+
58
+ def unsubscribe(self, shards):
59
+ for shard, consume in shards:
60
+ try:
61
+ self._all_heart_shards.pop(shard)
62
+ except KeyError as e:
63
+ logger.error("shard {} is not in all heart shard", shard)
64
+
65
+ def stop(self):
66
+ self._is_stop = True
67
+
68
+
69
+ def _convert_all_heart_shards(all_heart_shards):
70
+ shards = []
71
+ for key, value in all_heart_shards.items():
72
+ shards.append(key)
73
+ return shards
@@ -0,0 +1,179 @@
1
+ from concurrent.futures import ThreadPoolExecutor
2
+
3
+ from loguru import logger
4
+
5
+ from consumer.client.consumer_client_adapter import LogConsumerClientAdapter
6
+ from consumer.core.consumer_heartbeat import LogConsumerHeartBeat
7
+ from consumer.interface.consumer_check_point_tracker import DefaultLogConsumerCheckPointTracker
8
+ from consumer.interface.consumer_processor import ILogConsumerProcessor
9
+ from consumer.model.consumer_config import ConsumerConfig
10
+ from consumer.model.log_data import FetchedLogData
11
+ from consumer.model.task_result import TaskResult, ProcessTaskResult
12
+ from consumer.task.consumer_fetch_task import LogConsumerFetchTask, consumer_fetch_log
13
+ from consumer.task.initial_task import InitializeTask, initialize_task
14
+ from consumer.task.process_task import ProcessTask, process_task
15
+ from consumer.task.shutdown_task import ShutDownTask, shutdown_task
16
+ from huaweicloud_encryptionsdk._lts_sdk.utils import common
17
+
18
+ INITIALIZING = "INITIALIZING"
19
+ PROCESSING = "PROCESSING"
20
+ SHUTTING_DOWN = "SHUTTING_DOWN"
21
+ SHUTDOWN_COMPLETE = "SHUTDOWN_COMPLETE"
22
+
23
+
24
+ class LogShardConsumer(object):
25
+ def __init__(self, client_adapter: LogConsumerClientAdapter, shard_id, processor: ILogConsumerProcessor,
26
+ config: ConsumerConfig, heart_beat: LogConsumerHeartBeat):
27
+ self.client_adapter = client_adapter
28
+ self.shard_id = shard_id
29
+ self.start_time = config.start_time_ns
30
+ self.end_time = config.end_time_ns
31
+ self.processor = processor
32
+ self.checkpoint_tracker = DefaultLogConsumerCheckPointTracker(client_adapter=client_adapter, config=config,
33
+ shard_id=shard_id, heart_beat=heart_beat)
34
+ self.config = config
35
+ self.executor = ThreadPoolExecutor(max_workers=100, thread_name_prefix="log_shard_consumer-")
36
+ self.next_fetch_cursor = ""
37
+ self.final_fetch_cursor = ""
38
+ self.fetch_data_future = None
39
+ self.task_future = None
40
+ self.last_fetched_data = None
41
+ self.last_log_error_time = 0
42
+ self.current_status = INITIALIZING
43
+ self.current_task = None
44
+ self._shutdown = False
45
+ self.fetch_data_task_exist = False
46
+
47
+ def consume(self):
48
+ self.check_and_generate_next_task()
49
+ if self.current_status == PROCESSING and self.last_fetched_data is None:
50
+ self.fetch_data()
51
+
52
+ def do_process_task_result(self, process_task_result):
53
+ checkpoint = process_task_result.rollback_checkpoint
54
+ if checkpoint is not None and len(checkpoint) > 0:
55
+ self.cancel_current_fetch()
56
+ self.next_fetch_cursor = checkpoint
57
+
58
+ def do_process_init_result(self, init_task_result):
59
+ self.next_fetch_cursor = init_task_result.start_time
60
+ self.final_fetch_cursor = init_task_result.end_time
61
+ self.checkpoint_tracker.initial_cursor = self.next_fetch_cursor
62
+ if init_task_result.cursor_persistent:
63
+ self.checkpoint_tracker.last_save_check_point = self.next_fetch_cursor
64
+
65
+ def fetch_data(self):
66
+ has_error = False
67
+ if self.fetch_data_future is not None:
68
+ if self.fetch_data_future.cancelled():
69
+ self.fetch_data_future = None
70
+ self.last_fetched_data = None
71
+ return
72
+ elif not self.fetch_data_future.done():
73
+ return
74
+ result = self.get_task_result(self.fetch_data_future)
75
+ if result is not None and result.error is None:
76
+ fetch = result.fetch_data
77
+ self.last_fetched_data = FetchedLogData(self.shard_id, fetch, result.next_cursor,
78
+ result.cursor)
79
+ self.next_fetch_cursor = result.next_cursor
80
+ self.sample_log_error(result)
81
+ has_error = result.error is not None
82
+ if not has_error:
83
+ task = LogConsumerFetchTask(self.client_adapter, self.shard_id, self.next_fetch_cursor,
84
+ self.final_fetch_cursor,
85
+ self.config)
86
+ self.fetch_data_future = self.executor.submit(consumer_fetch_log, task)
87
+ else:
88
+ self.fetch_data_future = None
89
+
90
+ def cancel_current_fetch(self):
91
+ if self.fetch_data_future is not None:
92
+ self.fetch_data_future.cancel()
93
+ self.get_task_result(self.fetch_data_future)
94
+ self.fetch_data_future = None
95
+ logger.info("cancel a fetch task, shard id: {}", self.shard_id)
96
+ self.last_fetched_data = None
97
+
98
+ def sample_log_error(self, result: TaskResult):
99
+ if result is not None and result.error is not None:
100
+ current_time = common.current_time_ms()
101
+ if current_time - self.last_log_error_time > 5 * 1000:
102
+ logger.warning("error is {}", result.error)
103
+ self.last_log_error_time = current_time
104
+
105
+ def update_status(self, task_success):
106
+ if self.current_status == SHUTTING_DOWN:
107
+ if self.current_task is None or task_success:
108
+ self.current_status = SHUTDOWN_COMPLETE
109
+ elif self.is_shutdown():
110
+ self.current_status = SHUTTING_DOWN
111
+ elif task_success:
112
+ if self.current_status == INITIALIZING:
113
+ self.current_status = PROCESSING
114
+
115
+ def generate_next_task(self):
116
+ next_task = None
117
+ logger.debug("when generate next task, status is {}", self.current_status)
118
+ if self.current_status == INITIALIZING:
119
+ next_task = InitializeTask(self.processor, self.client_adapter, self.shard_id, self.start_time,
120
+ self.end_time)
121
+ elif self.current_status == PROCESSING:
122
+ if self.last_fetched_data is not None:
123
+ self.checkpoint_tracker.current_cursor = self.last_fetched_data.cursor
124
+ self.checkpoint_tracker.next_cursor = self.last_fetched_data.next_cursor
125
+ next_task = ProcessTask(self.processor, self.last_fetched_data.fetchedData, self.checkpoint_tracker,
126
+ self.final_fetch_cursor)
127
+ self.last_fetched_data = None
128
+ else:
129
+ logger.debug("last fetched data is none")
130
+ elif self.current_status == SHUTTING_DOWN:
131
+ next_task = ShutDownTask(self.processor, self.checkpoint_tracker)
132
+ self.cancel_current_fetch()
133
+ if next_task is not None:
134
+ self.current_task = next_task
135
+ if isinstance(self.current_task, InitializeTask):
136
+ logger.debug("current task is initialize task")
137
+ self.task_future = self.executor.submit(initialize_task, self.current_task)
138
+ elif isinstance(self.current_task, ProcessTask):
139
+ logger.debug("current task is process task")
140
+ self.task_future = self.executor.submit(process_task, self.current_task)
141
+ elif isinstance(self.current_task, ShutDownTask):
142
+ logger.debug("current task is shutdown task")
143
+ self.task_future = self.executor.submit(shutdown_task, self.current_task)
144
+ else:
145
+ logger.debug("next task is none")
146
+
147
+ def check_and_generate_next_task(self):
148
+ if self.task_future is None or self.task_future.cancelled() or self.task_future.done():
149
+ task_success = False
150
+ result = self.get_task_result(self.task_future)
151
+ logger.debug("after get task result, result is {}", result)
152
+ self.task_future = None
153
+ if result is not None and result.error is None:
154
+ task_success = True
155
+ if self.current_status == INITIALIZING:
156
+ self.do_process_init_result(result)
157
+ elif isinstance(result, ProcessTaskResult):
158
+ self.do_process_task_result(result)
159
+ self.sample_log_error(result)
160
+ self.update_status(task_success)
161
+ self.generate_next_task()
162
+
163
+ def shutdown(self):
164
+ self._shutdown = True
165
+ if not self.is_shutdown():
166
+ self.check_and_generate_next_task()
167
+
168
+ def is_shutdown(self):
169
+ return self.current_status == SHUTDOWN_COMPLETE
170
+
171
+ @staticmethod
172
+ def get_task_result(future):
173
+ if future is not None and (future.done() or future.cancelled()):
174
+ try:
175
+ logger.debug("result type is {}", future)
176
+ return future.result()
177
+ except Exception as e:
178
+ logger.error("error retrieving task result, error: {}", e)
179
+ return None
@@ -0,0 +1,120 @@
1
+ from consumer.client.consumer_client_adapter import LogConsumerClientAdapter
2
+ from consumer.model.consumer_config import ConsumerConfig
3
+
4
+
5
+ class ILogConsumerCheckPointTracker(object):
6
+ def save_check_point(self, persistent: bool):
7
+ raise NotImplemented("please implement me")
8
+
9
+ def get_check_point(self) -> str:
10
+ raise NotImplemented("please implement me")
11
+
12
+ def get_current_cursor(self) -> str:
13
+ raise NotImplemented("please implement me")
14
+
15
+
16
+ class DefaultLogConsumerCheckPointTracker(ILogConsumerCheckPointTracker):
17
+
18
+ def __init__(self, client_adapter, config: ConsumerConfig, shard_id, heart_beat):
19
+ self._client_adapter = client_adapter
20
+ self._consumer = config.consumer
21
+ self._shard_id = shard_id
22
+ self._heart_beat = heart_beat
23
+
24
+ self._pending_check_point = ""
25
+ self._last_save_check_point = ""
26
+ self._next_cursor = ""
27
+ self._current_cursor = ""
28
+ self._initial_cursor = ""
29
+
30
+ @property
31
+ def client_adapter(self) -> LogConsumerClientAdapter:
32
+ return self._client_adapter
33
+
34
+ @property
35
+ def consumer(self):
36
+ return self._consumer
37
+
38
+ @consumer.setter
39
+ def consumer(self, value: str):
40
+ self._consumer = value
41
+
42
+ @property
43
+ def shard_id(self):
44
+ return self._shard_id
45
+
46
+ @shard_id.setter
47
+ def shard_id(self, value: str):
48
+ self._shard_id = value
49
+
50
+ @property
51
+ def pending_check_point(self):
52
+ return self._pending_check_point
53
+
54
+ @pending_check_point.setter
55
+ def pending_check_point(self, value: str):
56
+ self._pending_check_point = value
57
+
58
+ @property
59
+ def last_save_check_point(self):
60
+ return self._last_save_check_point
61
+
62
+ @last_save_check_point.setter
63
+ def last_save_check_point(self, value: str):
64
+ self._last_save_check_point = value
65
+
66
+ @property
67
+ def next_cursor(self):
68
+ return self._next_cursor
69
+
70
+ @next_cursor.setter
71
+ def next_cursor(self, value: str):
72
+ self._next_cursor = value
73
+
74
+ @property
75
+ def initial_cursor(self):
76
+ return self._initial_cursor
77
+
78
+ @initial_cursor.setter
79
+ def initial_cursor(self, value: str):
80
+ self._initial_cursor = value
81
+
82
+ @property
83
+ def current_cursor(self):
84
+ return self._current_cursor
85
+
86
+ @current_cursor.setter
87
+ def current_cursor(self, value: str):
88
+ self._current_cursor = value
89
+
90
+ def save_check_point(self, persistent: bool):
91
+ self._pending_check_point = self._next_cursor
92
+ if persistent:
93
+ return self.flush_check_point()
94
+ return None
95
+
96
+ def flush_check_point(self):
97
+ self._pending_check_point = self._next_cursor
98
+ checkpoint = self._pending_check_point
99
+ if isinstance(checkpoint, str):
100
+ if len(checkpoint) == 0 or checkpoint == self._last_save_check_point:
101
+ return None
102
+ elif isinstance(checkpoint, int):
103
+ if int == 0 or checkpoint == self._last_save_check_point:
104
+ return None
105
+ err = self._client_adapter.update_check_point(self._shard_id, self._consumer, checkpoint)
106
+ if err is None:
107
+ self._last_save_check_point = checkpoint
108
+ return err
109
+
110
+ def get_check_point(self) -> str:
111
+ if len(self._pending_check_point) != 0:
112
+ return self._pending_check_point
113
+ else:
114
+ return self._initial_cursor
115
+
116
+ def get_current_cursor(self) -> str:
117
+ return self._current_cursor
118
+
119
+ def consume_data_end_flush_checkpoint(self):
120
+ return self.flush_check_point()
@@ -0,0 +1,18 @@
1
+ from typing import List
2
+
3
+ from consumer.interface.consumer_check_point_tracker import ILogConsumerCheckPointTracker
4
+ from consumer.model.log_data import LogData
5
+
6
+
7
+ class ILogConsumerProcessor(object):
8
+ def initialize(self, shard_id):
9
+ raise NotImplemented("please implement me")
10
+
11
+ def process(self, log_group: List[LogData], tracker: ILogConsumerCheckPointTracker) -> str:
12
+ raise NotImplemented("please implement me")
13
+
14
+ def shutdown(self, tracker: ILogConsumerCheckPointTracker):
15
+ raise NotImplemented("please implement me")
16
+
17
+ def shard_consumer_thread_success(self, shard_id, is_success):
18
+ pass
@@ -0,0 +1,3 @@
1
+ class ILogConsumerProcessorFactory(object):
2
+ def generate_processor(self):
3
+ raise NotImplemented("please implement me")
@@ -0,0 +1,20 @@
1
+ from huaweicloud_encryptionsdk._lts_sdk.utils import common
2
+
3
+
4
+ class ShardCheckPoint:
5
+ def __init__(self):
6
+ self.shard_id = ""
7
+ self.checkpoint = 0
8
+ self.update_time = 0
9
+ self.consumer_name = ""
10
+
11
+ def __str__(self):
12
+ return common.convert_obj2_json_str(self)
13
+
14
+
15
+ class Cursor(object):
16
+ def __init__(self):
17
+ self.cursor = ""
18
+
19
+ def __str__(self):
20
+ return common.convert_obj2_json_str(self)
@@ -0,0 +1,27 @@
1
+ import uuid
2
+
3
+
4
+ class ConsumerConfig(object):
5
+ def __init__(self, endpoint, region_name, project_id, log_group_id, log_stream_id, access_key, access_secret,
6
+ consumer_group_name, start_time_ns, end_time_ns, batch_size, heartbeat_interval_mill=1000,
7
+ fetch_interval_mill=200, auto_commit_enable=True, auto_commit_interval_ms=60 * 1000, timeout_sec=60,
8
+ unload_after_commit_enable=False):
9
+ self.endpoint = endpoint
10
+ self.region_name = region_name
11
+ self.project_id = project_id
12
+ self.log_group_id = log_group_id
13
+ self.log_stream_id = log_stream_id
14
+ self.access_key = access_key
15
+ self.access_secret = access_secret
16
+ self.consumer_group_name = consumer_group_name
17
+ self.start_time_ns = start_time_ns
18
+ self.end_time_ns = end_time_ns
19
+ self.consumer = str(uuid.uuid4())
20
+ self.is_compress = True
21
+ self.heartbeat_interval_mill = heartbeat_interval_mill
22
+ self.fetch_interval_mill = fetch_interval_mill
23
+ self.auto_commit_enable = auto_commit_enable
24
+ self.auto_commit_interval_ms = auto_commit_interval_ms
25
+ self.timeout_sec = timeout_sec
26
+ self.unload_after_commit_enable = unload_after_commit_enable
27
+ self.batch_size = batch_size
@@ -0,0 +1,18 @@
1
+ class LogData(object):
2
+ def __init__(self):
3
+ self.labels = {}
4
+
5
+
6
+ class BatchGetLog(object):
7
+ def __init__(self):
8
+ self.count = 0
9
+ self.next = ""
10
+ self.logs = LogData()
11
+
12
+
13
+ class FetchedLogData(object):
14
+ def __init__(self, shard_id, fetched_data, next_cursor, cursor):
15
+ self.shard_id = shard_id
16
+ self.cursor = cursor
17
+ self.next_cursor = next_cursor
18
+ self.fetchedData = fetched_data
@@ -0,0 +1,40 @@
1
+ from huaweicloud_encryptionsdk._lts_sdk.utils import common
2
+
3
+
4
+ class TaskResult(object):
5
+ def __init__(self, error):
6
+ self.error = error
7
+
8
+ def __str__(self):
9
+ return common.convert_obj2_json_str(self.error)
10
+
11
+
12
+ class FetchTaskResult(TaskResult):
13
+ def __init__(self, fetch_data, cursor, next_cursor):
14
+ super().__init__(None)
15
+ self.fetch_data = fetch_data
16
+ self.cursor = cursor
17
+ self.next_cursor = next_cursor
18
+
19
+ def __str__(self):
20
+ return common.convert_obj2_json_str(self)
21
+
22
+
23
+ class InitTaskResult(TaskResult):
24
+ def __init__(self, start_time, end_time, cursor_persistent):
25
+ super().__init__(None)
26
+ self.start_time = start_time
27
+ self.end_time = end_time
28
+ self.cursor_persistent = cursor_persistent
29
+
30
+ def __str__(self):
31
+ return common.convert_obj2_json_str(self)
32
+
33
+
34
+ class ProcessTaskResult(TaskResult):
35
+ def __init__(self, rollback_checkpoint):
36
+ super().__init__(None)
37
+ self.rollback_checkpoint = rollback_checkpoint
38
+
39
+ def __str__(self):
40
+ return common.convert_obj2_json_str(self)
@@ -0,0 +1,53 @@
1
+ import time
2
+
3
+ from loguru import logger
4
+
5
+ from consumer.client.consumer_client_adapter import LogConsumerClientAdapter
6
+ from consumer.model.consumer_config import ConsumerConfig
7
+ from consumer.model.task_result import TaskResult, FetchTaskResult
8
+
9
+
10
+ class LogConsumerFetchTask(object):
11
+ def __init__(self, client_adapter: LogConsumerClientAdapter, shard_id, cursor, final_fetch_cursor,
12
+ config: ConsumerConfig):
13
+ self.client_adapter = client_adapter
14
+ self.shard_id = shard_id
15
+ self.cursor = cursor
16
+ self.final_fetch_cursor = final_fetch_cursor
17
+ self.config = config
18
+
19
+
20
+ def consumer_fetch_log(task: LogConsumerFetchTask) -> TaskResult:
21
+ err = None
22
+ for i in range(2):
23
+ if task.final_fetch_cursor is not None and len(task.final_fetch_cursor) > 0:
24
+ err, batch_log = task.client_adapter.batch_get_logs(task.shard_id, task.config.batch_size, task.cursor,
25
+ task.final_fetch_cursor)
26
+ else:
27
+ err, batch_log = task.client_adapter.batch_get_logs(task.shard_id, task.config.batch_size, task.cursor,
28
+ "")
29
+ if err is not None:
30
+ logger.error("failed pull data from shard {}, cursor {}, error {}", task.shard_id, task.cursor, err)
31
+ time.sleep(0.2)
32
+ continue
33
+ else:
34
+ fetched_data = batch_log.logs
35
+ logger.debug("shard {}, cursor {}, next cursor {}, response size: {}", task.shard_id, task.cursor,
36
+ batch_log.next, batch_log.count)
37
+ next_cursor = batch_log.next
38
+ if isinstance(next_cursor, int):
39
+ logger.debug("int cursor is {}", next_cursor)
40
+ if next_cursor == 0:
41
+ logger.info("shard {} next cursor is empty, set to current int cursor {}", task.shard_id,
42
+ task.cursor)
43
+ next_cursor = task.cursor
44
+ if isinstance(next_cursor, str):
45
+ logger.debug("str cursor is {}", next_cursor)
46
+ if len(next_cursor) == 0:
47
+ logger.info("shard {} next cursor is empty, set to current str cursor {}", task.shard_id,
48
+ task.cursor)
49
+ next_cursor = task.cursor
50
+ return FetchTaskResult(fetched_data, task.cursor, next_cursor)
51
+
52
+ if err is not None:
53
+ return TaskResult(err)