yellowstone-fumarole-client 0.1.0rc2__tar.gz → 0.2.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 (23) hide show
  1. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/PKG-INFO +35 -30
  2. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/README.md +33 -24
  3. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/pyproject.toml +3 -7
  4. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/__init__.py +88 -19
  5. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/config.py +17 -1
  6. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/grpc_connectivity.py +11 -28
  7. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/runtime/aio.py +86 -70
  8. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/runtime/state_machine.py +23 -22
  9. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/utils/aio.py +0 -2
  10. yellowstone_fumarole_client-0.2.0/yellowstone_fumarole_client/utils/collections.py +37 -0
  11. yellowstone_fumarole_client-0.2.0/yellowstone_fumarole_proto/fumarole_pb2.py +134 -0
  12. yellowstone_fumarole_client-0.1.0rc2/yellowstone_fumarole_proto/fumarole_v2_pb2.pyi → yellowstone_fumarole_client-0.2.0/yellowstone_fumarole_proto/fumarole_pb2.pyi +51 -5
  13. yellowstone_fumarole_client-0.1.0rc2/yellowstone_fumarole_proto/fumarole_v2_pb2_grpc.py → yellowstone_fumarole_client-0.2.0/yellowstone_fumarole_proto/fumarole_pb2_grpc.py +155 -69
  14. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/geyser_pb2.py +39 -35
  15. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/geyser_pb2.pyi +15 -2
  16. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/geyser_pb2_grpc.py +44 -1
  17. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/solana_storage_pb2.py +32 -32
  18. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/solana_storage_pb2.pyi +6 -3
  19. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/solana_storage_pb2_grpc.py +1 -1
  20. yellowstone_fumarole_client-0.1.0rc2/yellowstone_fumarole_proto/fumarole_v2_pb2.py +0 -122
  21. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/runtime/__init__.py +0 -0
  22. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_client/utils/__init__.py +0 -0
  23. {yellowstone_fumarole_client-0.1.0rc2 → yellowstone_fumarole_client-0.2.0}/yellowstone_fumarole_proto/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: yellowstone-fumarole-client
3
- Version: 0.1.0rc2
3
+ Version: 0.2.0
4
4
  Summary: Yellowstone Fumarole Python Client
5
5
  Home-page: https://github.com/rpcpool/yellowstone-fumarole
6
6
  Author: Louis-Vincent
@@ -8,14 +8,9 @@ Author-email: louis-vincent@triton.one
8
8
  Requires-Python: >=3.13,<4.0
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.13
11
- Requires-Dist: asyncio (>=3.4.3,<4.0.0)
12
- Requires-Dist: base58 (>=2.1.1,<3.0.0)
13
- Requires-Dist: click (>=8.1.7,<9.0.0)
14
11
  Requires-Dist: grpcio (>=1.71.1,<2.0.0)
15
- Requires-Dist: protobuf (>=5.29.1,<6.0.0)
12
+ Requires-Dist: protobuf (>=6.32.0,<7.0.0)
16
13
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
17
- Requires-Dist: tabulate (>=0.9.0,<0.10.0)
18
- Requires-Dist: toml (>=0.10.2,<0.11.0)
19
14
  Project-URL: Repository, https://github.com/rpcpool/yellowstone-fumarole
20
15
  Description-Content-Type: text/markdown
21
16
 
@@ -83,33 +78,43 @@ async def dragonsmouth_like_session(fumarole_config):
83
78
  session = await client.dragonsmouth_subscribe(
84
79
  consumer_group_name="test",
85
80
  request=SubscribeRequest(
86
- # accounts={"fumarole": SubscribeRequestFilterAccounts()},
81
+ accounts={"fumarole": SubscribeRequestFilterAccounts()},
87
82
  transactions={"fumarole": SubscribeRequestFilterTransactions()},
88
83
  blocks_meta={"fumarole": SubscribeRequestFilterBlocksMeta()},
89
84
  entry={"fumarole": SubscribeRequestFilterEntry()},
90
85
  slots={"fumarole": SubscribeRequestFilterSlots()},
91
86
  ),
92
87
  )
93
- dragonsmouth_source = session.source
94
- handle = session.fumarole_handle
95
- block_map = defaultdict(BlockConstruction)
96
- while True:
97
- tasks = [asyncio.create_task(dragonsmouth_source.get()), handle]
98
- done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
99
- for t in done:
100
- if tasks[0] == t:
101
- result: SubscribeUpdate = t.result()
102
- if result.HasField("block_meta"):
103
- block_meta: SubscribeUpdateBlockMeta = result.block_meta
104
- elif result.HasField("transaction"):
105
- tx: SubscribeUpdateTransaction = result.transaction
106
- elif result.HasField("account"):
107
- account: SubscribeUpdateAccount = result.account
108
- elif result.HasField("entry"):
109
- entry: SubscribeUpdateEntry = result.entry
110
- elif result.HasField("slot"):
111
- result: SubscribeUpdateSlot = result.slot
112
- else:
113
- result = t.result()
114
- raise RuntimeError("failed to get dragonsmouth source: %s" % result)
88
+ async with session:
89
+ dragonsmouth_like_source = session.source
90
+ # result: SubscribeUpdate
91
+ async for result in dragonsmouth_like_source:
92
+ if result.HasField("block_meta"):
93
+ block_meta: SubscribeUpdateBlockMeta = result.block_meta
94
+ elif result.HasField("transaction"):
95
+ tx: SubscribeUpdateTransaction = result.transaction
96
+ elif result.HasField("account"):
97
+ account: SubscribeUpdateAccount = result.account
98
+ elif result.HasField("entry"):
99
+ entry: SubscribeUpdateEntry = result.entry
100
+ elif result.HasField("slot"):
101
+ result: SubscribeUpdateSlot = result.slot
102
+
103
+ # OUTSIDE THE SCOPE, YOU SHOULD NEVER USE `session` again.
104
+ ```
105
+
106
+
107
+ At any point you can get a rough estimate if you are progression through the slot using `DragonsmouthAdapterSession.stats()` call:
108
+
109
+ ```python
110
+
111
+ async with session:
112
+ stats: FumaroleSubscribeStats = session.stats()
113
+ print(f"{stats.log_committed_offset}, {stats.log_committable_offset}, {stats.max_slot_seen}")
115
114
  ```
115
+
116
+ `log_committed_offset` : what have been ACK so for to fumarole remote service.
117
+ `log_committable_offset` : what can be ACK to next commit call.
118
+ `max_slot_seen` : maximum slot seen in the inner fumarole client state -- not yet processed by your code.
119
+
120
+
@@ -62,33 +62,42 @@ async def dragonsmouth_like_session(fumarole_config):
62
62
  session = await client.dragonsmouth_subscribe(
63
63
  consumer_group_name="test",
64
64
  request=SubscribeRequest(
65
- # accounts={"fumarole": SubscribeRequestFilterAccounts()},
65
+ accounts={"fumarole": SubscribeRequestFilterAccounts()},
66
66
  transactions={"fumarole": SubscribeRequestFilterTransactions()},
67
67
  blocks_meta={"fumarole": SubscribeRequestFilterBlocksMeta()},
68
68
  entry={"fumarole": SubscribeRequestFilterEntry()},
69
69
  slots={"fumarole": SubscribeRequestFilterSlots()},
70
70
  ),
71
71
  )
72
- dragonsmouth_source = session.source
73
- handle = session.fumarole_handle
74
- block_map = defaultdict(BlockConstruction)
75
- while True:
76
- tasks = [asyncio.create_task(dragonsmouth_source.get()), handle]
77
- done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
78
- for t in done:
79
- if tasks[0] == t:
80
- result: SubscribeUpdate = t.result()
81
- if result.HasField("block_meta"):
82
- block_meta: SubscribeUpdateBlockMeta = result.block_meta
83
- elif result.HasField("transaction"):
84
- tx: SubscribeUpdateTransaction = result.transaction
85
- elif result.HasField("account"):
86
- account: SubscribeUpdateAccount = result.account
87
- elif result.HasField("entry"):
88
- entry: SubscribeUpdateEntry = result.entry
89
- elif result.HasField("slot"):
90
- result: SubscribeUpdateSlot = result.slot
91
- else:
92
- result = t.result()
93
- raise RuntimeError("failed to get dragonsmouth source: %s" % result)
94
- ```
72
+ async with session:
73
+ dragonsmouth_like_source = session.source
74
+ # result: SubscribeUpdate
75
+ async for result in dragonsmouth_like_source:
76
+ if result.HasField("block_meta"):
77
+ block_meta: SubscribeUpdateBlockMeta = result.block_meta
78
+ elif result.HasField("transaction"):
79
+ tx: SubscribeUpdateTransaction = result.transaction
80
+ elif result.HasField("account"):
81
+ account: SubscribeUpdateAccount = result.account
82
+ elif result.HasField("entry"):
83
+ entry: SubscribeUpdateEntry = result.entry
84
+ elif result.HasField("slot"):
85
+ result: SubscribeUpdateSlot = result.slot
86
+
87
+ # OUTSIDE THE SCOPE, YOU SHOULD NEVER USE `session` again.
88
+ ```
89
+
90
+
91
+ At any point you can get a rough estimate if you are progression through the slot using `DragonsmouthAdapterSession.stats()` call:
92
+
93
+ ```python
94
+
95
+ async with session:
96
+ stats: FumaroleSubscribeStats = session.stats()
97
+ print(f"{stats.log_committed_offset}, {stats.log_committable_offset}, {stats.max_slot_seen}")
98
+ ```
99
+
100
+ `log_committed_offset` : what have been ACK so for to fumarole remote service.
101
+ `log_committable_offset` : what can be ACK to next commit call.
102
+ `max_slot_seen` : maximum slot seen in the inner fumarole client state -- not yet processed by your code.
103
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "yellowstone-fumarole-client"
3
- version = "0.1.0rc2"
3
+ version = "0.2.0"
4
4
  homepage = "https://github.com/rpcpool/yellowstone-fumarole"
5
5
  repository = "https://github.com/rpcpool/yellowstone-fumarole"
6
6
  description = "Yellowstone Fumarole Python Client"
@@ -14,13 +14,8 @@ packages = [
14
14
 
15
15
  [tool.poetry.dependencies]
16
16
  python = "^3.13"
17
- click = "^8.1.7"
18
17
  grpcio = "^1.71.1"
19
- protobuf = "^5.29.1"
20
- toml = "^0.10.2"
21
- base58 = "^2.1.1"
22
- tabulate = "^0.9.0"
23
- asyncio = "^3.4.3"
18
+ protobuf = "^6.32.0"
24
19
  pyyaml = "^6.0.2"
25
20
 
26
21
  [tool.poetry.group.test.dependencies]
@@ -30,6 +25,7 @@ pytest = "^8.3.4"
30
25
  grpcio-tools = "^1.68.1"
31
26
  black = "^24.10.0"
32
27
  pytest-asyncio = "^0.26.0"
28
+ deptry = "^0.23.1"
33
29
 
34
30
  [build-system]
35
31
  requires = ["poetry-core"]
@@ -3,18 +3,21 @@ import logging
3
3
  from yellowstone_fumarole_client.grpc_connectivity import (
4
4
  FumaroleGrpcConnector,
5
5
  )
6
- from typing import Dict, Optional
6
+ from typing import AsyncGenerator, Optional
7
7
  from dataclasses import dataclass
8
- from . import config
8
+ from yellowstone_fumarole_client.config import FumaroleConfig
9
9
  from yellowstone_fumarole_client.runtime.aio import (
10
10
  AsyncioFumeDragonsmouthRuntime,
11
- FumaroleSM,
12
11
  DEFAULT_GC_INTERVAL,
13
12
  DEFAULT_SLOT_MEMORY_RETENTION,
14
13
  GrpcSlotDownloader,
15
14
  )
15
+ from yellowstone_fumarole_client.runtime.state_machine import (
16
+ FumaroleSM,
17
+ FumeOffset,
18
+ )
16
19
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeRequest, SubscribeUpdate
17
- from yellowstone_fumarole_proto.fumarole_v2_pb2 import (
20
+ from yellowstone_fumarole_proto.fumarole_pb2 import (
18
21
  ControlResponse,
19
22
  VersionRequest,
20
23
  VersionResponse,
@@ -29,9 +32,11 @@ from yellowstone_fumarole_proto.fumarole_v2_pb2 import (
29
32
  CreateConsumerGroupRequest,
30
33
  CreateConsumerGroupResponse,
31
34
  )
32
- from yellowstone_fumarole_proto.fumarole_v2_pb2_grpc import FumaroleStub
35
+ from yellowstone_fumarole_proto.fumarole_pb2_grpc import FumaroleStub
33
36
  import grpc
34
37
 
38
+ from yellowstone_fumarole_client import config
39
+
35
40
  __all__ = [
36
41
  "FumaroleClient",
37
42
  "FumaroleConfig",
@@ -44,7 +49,7 @@ __all__ = [
44
49
  ]
45
50
 
46
51
  # Constants
47
- DEFAULT_DRAGONSMOUTH_CAPACITY = 10000
52
+ DEFAULT_DRAGONSMOUTH_CAPACITY = 100000
48
53
  DEFAULT_COMMIT_INTERVAL = 5.0 # seconds
49
54
  DEFAULT_MAX_SLOT_DOWNLOAD_ATTEMPT = 3
50
55
  DEFAULT_CONCURRENT_DOWNLOAD_LIMIT_PER_TCP = 10
@@ -72,10 +77,23 @@ class FumaroleSubscribeConfig:
72
77
  # The interval at which to perform garbage collection on the slot memory.
73
78
  gc_interval: int = DEFAULT_GC_INTERVAL
74
79
 
75
- # The retention period for slot memory in seconds.
80
+ # How many processed slot numbers to retain in memory to avoid duplication.
76
81
  slot_memory_retention: int = DEFAULT_SLOT_MEMORY_RETENTION
77
82
 
78
83
 
84
+ @dataclass
85
+ class FumaroleSubscribeStats:
86
+ """Commit/slot statistics for the Fumarole subscribe session."""
87
+
88
+ # Last committed log offset in Fumarole -- this is a low-level, implementation detail.
89
+ # NOTE: this should not be part as business logic, can change any time.
90
+ log_committed_offset: FumeOffset
91
+ # NOTE:: this is a low-level information, can change any time.
92
+ log_committable_offset: FumeOffset
93
+ # Max slot seen by the in the current session - does not mean it has been processed.
94
+ max_slot_seen: int
95
+
96
+
79
97
  # DragonsmouthAdapterSession
80
98
  @dataclass
81
99
  class DragonsmouthAdapterSession:
@@ -85,10 +103,31 @@ class DragonsmouthAdapterSession:
85
103
  sink: asyncio.Queue
86
104
 
87
105
  # The queue for receiving SubscribeUpdate from the dragonsmouth stream.
88
- source: asyncio.Queue
106
+ source: AsyncGenerator[SubscribeUpdate, None]
89
107
 
90
108
  # The task handle for the fumarole runtime.
91
- fumarole_handle: asyncio.Task
109
+ _fumarole_handle: asyncio.Task
110
+
111
+ _sm: FumaroleSM
112
+
113
+ async def __aenter__(self):
114
+ """Enter the session context."""
115
+ return self
116
+
117
+ async def __aexit__(self, exc_type, exc_value, traceback):
118
+ self.sink.shutdown()
119
+ self._fumarole_handle.cancel()
120
+
121
+ def stats(self) -> FumaroleSubscribeStats:
122
+ """Get low-level statistics of the Fumarole state-machine."""
123
+ commitable = self._sm.committable_offset
124
+ committed = self._sm.last_committed_offset
125
+ max_slot = self._sm.max_slot_detected
126
+ return FumaroleSubscribeStats(
127
+ log_committed_offset=committed,
128
+ log_committable_offset=commitable,
129
+ max_slot_seen=max_slot,
130
+ )
92
131
 
93
132
 
94
133
  # FumaroleClient
@@ -117,7 +156,7 @@ class FumaroleClient:
117
156
  async def version(self) -> VersionResponse:
118
157
  """Get the version of the Fumarole server."""
119
158
  request = VersionRequest()
120
- response = await self.stub.version(request)
159
+ response = await self.stub.Version(request)
121
160
  return response
122
161
 
123
162
  async def dragonsmouth_subscribe(
@@ -162,12 +201,12 @@ class FumaroleClient:
162
201
  try:
163
202
  update = await fume_control_plane_q.get()
164
203
  yield update
165
- except asyncio.QueueShutDown:
204
+ except (asyncio.CancelledError, asyncio.QueueShutDown):
166
205
  break
167
206
 
168
- fume_control_plane_stream_rx: grpc.aio.StreamStreamMultiCallable = (
169
- self.stub.Subscribe(control_plane_sink())
170
- )
207
+ fume_control_plane_stream_rx: grpc.aio.StreamStreamCall = self.stub.Subscribe(
208
+ control_plane_sink()
209
+ ) # it's actually InterceptedStreamStreamCall, but grpc lib doesn't export it
171
210
 
172
211
  control_response: ControlResponse = await fume_control_plane_stream_rx.read()
173
212
  init = control_response.init
@@ -187,8 +226,12 @@ class FumaroleClient:
187
226
  await fume_control_plane_rx_q.put(update)
188
227
  except asyncio.QueueShutDown:
189
228
  break
229
+ except asyncio.CancelledError:
230
+ break
231
+ finally:
232
+ fume_control_plane_rx_q.shutdown()
190
233
 
191
- _cp_src_task = asyncio.create_task(control_plane_source())
234
+ control_plane_src_task = asyncio.create_task(control_plane_source())
192
235
 
193
236
  FumaroleClient.logger.debug(f"Control response: {control_response}")
194
237
 
@@ -219,12 +262,38 @@ class FumaroleClient:
219
262
  max_concurrent_download=config.concurrent_download_limit,
220
263
  )
221
264
 
222
- fumarole_handle = asyncio.create_task(rt.run())
223
- FumaroleClient.logger.debug(f"Fumarole handle created: {fumarole_handle}")
265
+ async def rt_run(rt):
266
+ async with rt as rt:
267
+ await rt.run()
268
+
269
+ rt_task = asyncio.create_task(rt_run(rt))
270
+
271
+ async def fumarole_overseer():
272
+ done, pending = await asyncio.wait(
273
+ [rt_task, control_plane_src_task], return_when=asyncio.FIRST_COMPLETED
274
+ )
275
+ for t in pending:
276
+ t.cancel()
277
+
278
+ fumarole_handle = asyncio.create_task(fumarole_overseer())
279
+
280
+ async def source_gen() -> AsyncGenerator[SubscribeUpdate, None]:
281
+ try:
282
+ while True:
283
+ update = await dragonsmouth_outlet.get()
284
+ yield update
285
+ except asyncio.CancelledError:
286
+ pass
287
+ except asyncio.Queue:
288
+ pass
289
+ finally:
290
+ dragonsmouth_outlet.shutdown()
291
+
224
292
  return DragonsmouthAdapterSession(
225
293
  sink=subscribe_request_queue,
226
- source=dragonsmouth_outlet,
227
- fumarole_handle=fumarole_handle,
294
+ source=source_gen(),
295
+ _fumarole_handle=fumarole_handle,
296
+ _sm=sm,
228
297
  )
229
298
 
230
299
  async def list_consumer_groups(
@@ -1,14 +1,19 @@
1
1
  from dataclasses import dataclass
2
- from typing import Dict, Optional
2
+ from typing import Dict, Literal, Optional
3
3
  import yaml
4
4
 
5
5
 
6
+ SUPPORTED_COMPRESSION = ["gzip"]
7
+ SupportedCompression = Literal["gzip"]
8
+
9
+
6
10
  @dataclass
7
11
  class FumaroleConfig:
8
12
  endpoint: str
9
13
  x_token: Optional[str] = None
10
14
  max_decoding_message_size_bytes: int = 512_000_000
11
15
  x_metadata: Dict[str, str] = None
16
+ response_compression: Optional[SupportedCompression] = None
12
17
 
13
18
  def __post_init__(self):
14
19
  self.x_metadata = self.x_metadata or {}
@@ -16,6 +21,14 @@ class FumaroleConfig:
16
21
  @classmethod
17
22
  def from_yaml(cls, fileobj) -> "FumaroleConfig":
18
23
  data = yaml.safe_load(fileobj)
24
+ response_compression = data.get(
25
+ "response_compression", cls.response_compression
26
+ )
27
+ if (
28
+ response_compression is not None
29
+ and response_compression not in SUPPORTED_COMPRESSION
30
+ ):
31
+ raise ValueError(f"response_compression must be in {SUPPORTED_COMPRESSION}")
19
32
  return cls(
20
33
  endpoint=data["endpoint"],
21
34
  x_token=data.get("x-token") or data.get("x_token"),
@@ -23,4 +36,7 @@ class FumaroleConfig:
23
36
  "max_decoding_message_size_bytes", cls.max_decoding_message_size_bytes
24
37
  ),
25
38
  x_metadata=data.get("x-metadata", {}),
39
+ response_compression=data.get(
40
+ "response_compression", cls.response_compression
41
+ ),
26
42
  )
@@ -2,7 +2,7 @@ import logging
2
2
  from typing import Optional
3
3
  import grpc
4
4
  from yellowstone_fumarole_client.config import FumaroleConfig
5
- from yellowstone_fumarole_proto.fumarole_v2_pb2_grpc import FumaroleStub
5
+ from yellowstone_fumarole_proto.fumarole_pb2_grpc import FumaroleStub
6
6
 
7
7
  X_TOKEN_HEADER = "x-token"
8
8
 
@@ -31,34 +31,8 @@ class TritonAuthMetadataPlugin(grpc.AuthMetadataPlugin):
31
31
  return _triton_sign_request(callback, self.x_token, None)
32
32
 
33
33
 
34
- def grpc_channel(endpoint: str, x_token=None, compression=None, *grpc_options):
35
- options = [("grpc.max_receive_message_length", 111111110), *grpc_options]
36
- if x_token is not None:
37
- auth = TritonAuthMetadataPlugin(x_token)
38
- # ssl_creds allow you to use our https endpoint
39
- # grpc.ssl_channel_credentials with no arguments will look through your CA trust store.
40
- ssl_creds = grpc.ssl_channel_credentials()
41
-
42
- # call credentials will be sent on each request if setup with composite_channel_credentials.
43
- call_creds: grpc.CallCredentials = grpc.metadata_call_credentials(auth)
44
-
45
- # Combined creds will store the channel creds aswell as the call credentials
46
- combined_creds = grpc.composite_channel_credentials(ssl_creds, call_creds)
47
-
48
- return grpc.secure_channel(
49
- endpoint,
50
- credentials=combined_creds,
51
- compression=compression,
52
- options=options,
53
- )
54
- else:
55
- return grpc.insecure_channel(endpoint, compression=compression, options=options)
56
-
57
-
58
34
  # Because of a bug in grpcio library, multiple inheritance of ClientInterceptor subclasses does not work.
59
35
  # You have to create a new class for each type of interceptor you want to use.
60
-
61
-
62
36
  class MetadataInterceptor(
63
37
  grpc.aio.UnaryStreamClientInterceptor,
64
38
  grpc.aio.StreamUnaryClientInterceptor,
@@ -166,6 +140,11 @@ class FumaroleGrpcConnector:
166
140
  async def connect(self, *grpc_options) -> FumaroleStub:
167
141
  options = [("grpc.max_receive_message_length", 111111110), *grpc_options]
168
142
  interceptors = MetadataInterceptor(self.config.x_metadata).interceptors()
143
+ compression = (
144
+ grpc.Compression.Gzip
145
+ if self.config.response_compression == "gzip"
146
+ else None
147
+ )
169
148
  if self.config.x_token is not None:
170
149
  auth = TritonAuthMetadataPlugin(self.config.x_token)
171
150
  # ssl_creds allow you to use our https endpoint
@@ -184,6 +163,7 @@ class FumaroleGrpcConnector:
184
163
  self.endpoint,
185
164
  credentials=combined_creds,
186
165
  options=options,
166
+ compression=compression,
187
167
  interceptors=interceptors,
188
168
  )
189
169
  else:
@@ -191,7 +171,10 @@ class FumaroleGrpcConnector:
191
171
  "Using insecure channel without authentication"
192
172
  )
193
173
  channel = grpc.aio.insecure_channel(
194
- self.endpoint, options=options, interceptors=interceptors
174
+ self.endpoint,
175
+ options=options,
176
+ interceptors=interceptors,
177
+ compression=compression,
195
178
  )
196
179
 
197
180
  return FumaroleStub(channel)