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.
- examples/file_encryption_example.py +57 -0
- examples/key_capsule_encryption_example.py +240 -0
- examples/kms_discovery_encryption_example.py +56 -0
- examples/local_aes_encryption_example.py +59 -0
- examples/test_rsa.py +42 -0
- examples/test_sm2.py +38 -0
- examples/test_sm4_cbc.py +37 -0
- examples/test_sm4_gcm.py +37 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/METADATA +18 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/RECORD +174 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/WHEEL +5 -0
- huaweicloud_encryption_sdk_python-1.2.1.dist-info/top_level.txt +3 -0
- huaweicloud_encryptionsdk/__init__.py +5 -0
- huaweicloud_encryptionsdk/_apig_sdk/__init__.py +1 -0
- huaweicloud_encryptionsdk/_apig_sdk/signer.py +278 -0
- huaweicloud_encryptionsdk/_apig_sdk/signer_v11.py +70 -0
- huaweicloud_encryptionsdk/_apig_sdk/sm3_hash.py +141 -0
- huaweicloud_encryptionsdk/_lts_sdk/auth/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/auth/signer.py +174 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/client/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/client/consumer_client_adapter.py +59 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/client/http_client.py +211 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/client_consumer_worker.py +106 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/consumer_heartbeat.py +73 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/core/log_shard_consumer.py +179 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_check_point_tracker.py +120 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor.py +18 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/interface/consumer_processor_factory.py +3 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/check_point.py +20 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/consumer_config.py +27 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/log_data.py +18 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/model/task_result.py +40 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/consumer_fetch_task.py +53 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/initial_task.py +55 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/process_task.py +25 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer/task/shutdown_task.py +24 -0
- huaweicloud_encryptionsdk/_lts_sdk/consumer_main.py +88 -0
- huaweicloud_encryptionsdk/_lts_sdk/parallel_main.py +64 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/callback/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/callback/call_back.py +7 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/accumulator.py +135 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_thread_pool.py +107 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/io_worker.py +124 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/mover.py +69 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/core/producer.py +98 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/http_client.py +63 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/lts_http/simple_request.py +14 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/config.py +50 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/error.py +18 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/log.py +87 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/log_batch.py +154 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/lts_store.py +21 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/result.py +17 -0
- huaweicloud_encryptionsdk/_lts_sdk/producer/model/retry_queue.py +39 -0
- huaweicloud_encryptionsdk/_lts_sdk/serial_main.py +77 -0
- huaweicloud_encryptionsdk/_lts_sdk/utils/__init__.py +0 -0
- huaweicloud_encryptionsdk/_lts_sdk/utils/common.py +57 -0
- huaweicloud_encryptionsdk/_lts_sdk/utils/lts_threading.py +32 -0
- huaweicloud_encryptionsdk/cache/__init__.py +0 -0
- huaweicloud_encryptionsdk/cache/data_key_cache.py +79 -0
- huaweicloud_encryptionsdk/cache/local_data_key_cache.py +161 -0
- huaweicloud_encryptionsdk/common/__init__.py +0 -0
- huaweicloud_encryptionsdk/common/constants.py +15 -0
- huaweicloud_encryptionsdk/common/counting_output_stream.py +18 -0
- huaweicloud_encryptionsdk/common/crypto_factory.py +48 -0
- huaweicloud_encryptionsdk/common/ec_private_key_loader.py +43 -0
- huaweicloud_encryptionsdk/common/ecs_metadata_service.py +42 -0
- huaweicloud_encryptionsdk/common/file_path_for_example_constants.py +4 -0
- huaweicloud_encryptionsdk/common/utils.py +162 -0
- huaweicloud_encryptionsdk/exception/__init__.py +0 -0
- huaweicloud_encryptionsdk/exception/errors.py +109 -0
- huaweicloud_encryptionsdk/handler/__init__.py +0 -0
- huaweicloud_encryptionsdk/handler/cipher_handler.py +294 -0
- huaweicloud_encryptionsdk/handler/crypto_handler.py +24 -0
- huaweicloud_encryptionsdk/handler/default_crypto_handler.py +148 -0
- huaweicloud_encryptionsdk/handler/default_serialize_handler.py +45 -0
- huaweicloud_encryptionsdk/handler/file_decrypt_handler.py +101 -0
- huaweicloud_encryptionsdk/handler/file_encrypt_handler.py +30 -0
- huaweicloud_encryptionsdk/handler/serialize_handler.py +14 -0
- huaweicloud_encryptionsdk/huawei_config.py +49 -0
- huaweicloud_encryptionsdk/huawei_crypto.py +311 -0
- huaweicloud_encryptionsdk/keyrings/__init__.py +0 -0
- huaweicloud_encryptionsdk/keyrings/keyring.py +14 -0
- huaweicloud_encryptionsdk/keyrings/keyring_factory.py +10 -0
- huaweicloud_encryptionsdk/keyrings/kms_keyring_factory.py +21 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/__init__.py +0 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_discovery_keyring.py +51 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_key_capsule_keyring.py +100 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_keyring.py +155 -0
- huaweicloud_encryptionsdk/keyrings/kmskeyring/kms_multi_region_keyring.py +8 -0
- huaweicloud_encryptionsdk/keyrings/raw_keyring_factory.py +27 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/__init__.py +0 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_aes_keyring.py +63 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_keyring.py +112 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_rsa_keyring.py +55 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm2_keyring.py +75 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_cbc_keyring.py +66 -0
- huaweicloud_encryptionsdk/keyrings/rawkeyring/raw_sm4_keyring.py +70 -0
- huaweicloud_encryptionsdk/kms/__init__.py +0 -0
- huaweicloud_encryptionsdk/kms/create_key_capsule_request.py +35 -0
- huaweicloud_encryptionsdk/kms/create_key_capsule_response.py +19 -0
- huaweicloud_encryptionsdk/kms/decrypt_key_capsule_request.py +32 -0
- huaweicloud_encryptionsdk/kms/decrypt_key_capsule_response.py +19 -0
- huaweicloud_encryptionsdk/kms/kms_http_client.py +116 -0
- huaweicloud_encryptionsdk/log/__init__.py +0 -0
- huaweicloud_encryptionsdk/log/log_config.py +30 -0
- huaweicloud_encryptionsdk/log/log_file_backup.py +144 -0
- huaweicloud_encryptionsdk/log/log_metrics.py +132 -0
- huaweicloud_encryptionsdk/log/log_reporter_manager.py +163 -0
- huaweicloud_encryptionsdk/log/lts_sdk_producer.py +386 -0
- huaweicloud_encryptionsdk/log/lts_struct_log_builder.py +106 -0
- huaweicloud_encryptionsdk/meterialmanager/__init__.py +0 -0
- huaweicloud_encryptionsdk/meterialmanager/cache_crypto_meterial_manager.py +221 -0
- huaweicloud_encryptionsdk/meterialmanager/crypto_meterial_manager.py +19 -0
- huaweicloud_encryptionsdk/meterialmanager/data_key_generate.py +10 -0
- huaweicloud_encryptionsdk/meterialmanager/data_key_generate_factory.py +20 -0
- huaweicloud_encryptionsdk/meterialmanager/default_crypto_meterials_manager.py +71 -0
- huaweicloud_encryptionsdk/meterialmanager/key_capsule_data_key_generate.py +63 -0
- huaweicloud_encryptionsdk/meterialmanager/kms_data_key_generate.py +65 -0
- huaweicloud_encryptionsdk/meterialmanager/local_data_key_generate.py +13 -0
- huaweicloud_encryptionsdk/model/__init__.py +0 -0
- huaweicloud_encryptionsdk/model/access_point_config.py +9 -0
- huaweicloud_encryptionsdk/model/cipher_body.py +81 -0
- huaweicloud_encryptionsdk/model/cipher_header.py +405 -0
- huaweicloud_encryptionsdk/model/ciphertext_data_key.py +166 -0
- huaweicloud_encryptionsdk/model/crypto_result.py +11 -0
- huaweicloud_encryptionsdk/model/data_key_materials.py +17 -0
- huaweicloud_encryptionsdk/model/data_materials.py +11 -0
- huaweicloud_encryptionsdk/model/enums/__init__.py +0 -0
- huaweicloud_encryptionsdk/model/enums/access_point_type.py +28 -0
- huaweicloud_encryptionsdk/model/enums/crypto_algorithm.py +75 -0
- huaweicloud_encryptionsdk/model/enums/data_key_generate_type.py +20 -0
- huaweicloud_encryptionsdk/model/enums/key_provider_enum.py +19 -0
- huaweicloud_encryptionsdk/model/enums/keyring_type_enum.py +27 -0
- huaweicloud_encryptionsdk/model/key_capsule.py +10 -0
- huaweicloud_encryptionsdk/model/key_capsule_config.py +12 -0
- huaweicloud_encryptionsdk/model/kms_config.py +10 -0
- huaweicloud_encryptionsdk/model/request/__init__.py +0 -0
- huaweicloud_encryptionsdk/model/request/encrypt_request.py +10 -0
- huaweicloud_encryptionsdk/model/request/sign_request.py +2 -0
- huaweicloud_encryptionsdk/model/request/verify_request.py +2 -0
- huaweicloud_encryptionsdk/proof/__init__.py +0 -0
- huaweicloud_encryptionsdk/proof/attestation_document.py +36 -0
- huaweicloud_encryptionsdk/proof/collector/__init__.py +0 -0
- huaweicloud_encryptionsdk/proof/collector/cce_proof_collector.py +24 -0
- huaweicloud_encryptionsdk/proof/collector/ecs_proof_collector.py +11 -0
- huaweicloud_encryptionsdk/proof/collector/key_pair_proof_collector.py +55 -0
- huaweicloud_encryptionsdk/proof/collector/ma_proof_collector.py +51 -0
- huaweicloud_encryptionsdk/proof/private_key_decrypt_callback.py +7 -0
- huaweicloud_encryptionsdk/proof/proof_collector.py +11 -0
- huaweicloud_encryptionsdk/proof/proof_collector_factory.py +53 -0
- huaweicloud_encryptionsdk/proof/proof_info.py +10 -0
- huaweicloud_encryptionsdk/util/__init__.py +0 -0
- huaweicloud_encryptionsdk/util/common_utils.py +12 -0
- tests/__init__.py +0 -0
- tests/test_enums.py +84 -0
- tests/test_exceptions.py +38 -0
- tests/test_factories.py +71 -0
- tests/test_huawei_crypto.py +67 -0
- tests/test_imports.py +46 -0
- tests/test_kms_models.py +95 -0
- tests/test_log_file_backup.py +45 -0
- tests/test_lts_struct_log_builder.py +97 -0
- tests/test_models.py +142 -0
- 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
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|
|
@@ -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)
|
|
File without changes
|
|
@@ -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)
|