Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5c1fe2d

Browse files
committed
v2 stream provider
1 parent e592fbc commit 5c1fe2d

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

‎localstack-core/localstack/services/dynamodbstreams/dynamodbstreams_api.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
from bson.json_util import dumps
66

77
from localstack import config
8+
from localstack.aws.api import RequestContext
89
from localstack.aws.api.dynamodbstreams import StreamStatus, StreamViewType, TableName
910
from localstack.aws.connect import connect_to
11+
from localstack.services.dynamodb.v2.provider import DynamoDBProvider
1012
from localstack.services.dynamodbstreams.models import DynamoDbStreamsStore, dynamodbstreams_stores
1113
from localstack.utils.aws import arns, resources
1214
from localstack.utils.common import now_utc
@@ -211,3 +213,23 @@ def get_shard_id(stream: Dict, kinesis_shard_id: str) -> str:
211213
stream["shards_id_map"][kinesis_shard_id] = ddb_stream_shard_id
212214

213215
return ddb_stream_shard_id
216+
217+
218+
def get_original_region(
219+
context: RequestContext, stream_arn: str | None = None, table_name: str | None = None
220+
) -> str:
221+
"""
222+
In DDB Global tables, we forward all the requests to the original region, instead of really replicating the data.
223+
Since each table has a separate stream associated, we need to have a similar forwarding logic for DDB Streams.
224+
To determine the original region, we need the table name, that can be either provided here or determined from the
225+
ARN of the stream.
226+
"""
227+
if not stream_arn and not table_name:
228+
LOG.debug(
229+
"No Stream ARN or table name provided. Returning region '%s' from the request",
230+
context.region,
231+
)
232+
return context.region
233+
234+
table_name = table_name or table_name_from_stream_arn(stream_arn)
235+
return DynamoDBProvider.get_global_table_region(context=context, table_name=table_name)

‎localstack-core/localstack/services/dynamodbstreams/provider.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
get_dynamodbstreams_store,
3030
get_kinesis_client,
3131
get_kinesis_stream_name,
32+
get_original_region,
3233
get_shard_id,
3334
kinesis_shard_id,
3435
stream_name_from_stream_arn,
@@ -47,26 +48,6 @@
4748
}
4849

4950

50-
def get_original_region(
51-
context: RequestContext, stream_arn: str | None = None, table_name: str | None = None
52-
) -> str:
53-
"""
54-
In DDB Global tables, we forward all the requests to the original region, instead of really replicating the data.
55-
Since each table has a separate stream associated, we need to have a similar forwarding logic for DDB Streams.
56-
To determine the original region, we need the table name, that can be either provided here or determined from the
57-
ARN of the stream.
58-
"""
59-
if not stream_arn and not table_name:
60-
LOG.debug(
61-
"No Stream ARN or table name provided. Returning region '%s' from the request",
62-
context.region,
63-
)
64-
return context.region
65-
66-
table_name = table_name or table_name_from_stream_arn(stream_arn)
67-
return DynamoDBProvider.get_global_table_region(context=context, table_name=table_name)
68-
69-
7051
class DynamoDBStreamsProvider(DynamodbstreamsApi, ServiceLifecycleHook):
7152
def describe_stream(
7253
self,

‎localstack-core/localstack/services/dynamodbstreams/v2/provider.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
)
1616
from localstack.services.dynamodb.server import DynamodbServer
1717
from localstack.services.dynamodb.utils import modify_ddblocal_arns
18-
from localstack.services.dynamodb.v2.provider import DynamoDBProvider
18+
from localstack.services.dynamodb.v2.provider import DynamoDBProvider, modify_context_region
19+
from localstack.services.dynamodbstreams.dynamodbstreams_api import get_original_region
1920
from localstack.services.plugins import ServiceLifecycleHook
2021
from localstack.utils.aws.arns import parse_arn
2122

@@ -33,6 +34,14 @@ def on_after_init(self):
3334
def on_before_start(self):
3435
self.server.start_dynamodb()
3536

37+
def _forward_request(
38+
self, context: RequestContext, region: str | None, service_request: ServiceRequest
39+
) -> ServiceResponse:
40+
if region:
41+
with modify_context_region(context, region):
42+
return self.forward_request(context, service_request=service_request)
43+
return self.forward_request(context, service_request=service_request)
44+
3645
def forward_request(
3746
self, context: RequestContext, service_request: ServiceRequest = None
3847
) -> ServiceResponse:
@@ -55,12 +64,19 @@ def describe_stream(
5564
context: RequestContext,
5665
payload: DescribeStreamInput,
5766
) -> DescribeStreamOutput:
67+
global_table_region = get_original_region(context=context, stream_arn=payload["StreamArn"])
5868
request = payload.copy()
5969
request["StreamArn"] = self.modify_stream_arn_for_ddb_local(request.get("StreamArn", ""))
60-
return self.forward_request(context, request)
70+
return self._forward_request(
71+
context=context, service_request=request, region=global_table_region
72+
)
6173

6274
@handler("GetRecords", expand=False)
6375
def get_records(self, context: RequestContext, payload: GetRecordsInput) -> GetRecordsOutput:
76+
# Limitation note: With this current implementation, we are not able to get the records from a stream of a
77+
# replicated table. To do so, we would need to kept track of the emitted ShardIterators and the originating
78+
# region in `GetShardIterator`.
79+
6480
request = payload.copy()
6581
request["ShardIterator"] = self.modify_stream_arn_for_ddb_local(
6682
request.get("ShardIterator", "")
@@ -77,5 +93,8 @@ def get_shard_iterator(
7793

7894
@handler("ListStreams", expand=False)
7995
def list_streams(self, context: RequestContext, payload: ListStreamsInput) -> ListStreamsOutput:
96+
global_table_region = get_original_region(context=context, stream_arn=payload["TableName"])
8097
# TODO: look into `ExclusiveStartStreamArn` param
81-
return self.forward_request(context, payload)
98+
return self._forward_request(
99+
context=context, service_request=payload, region=global_table_region
100+
)

0 commit comments

Comments
 (0)