aws-elasticache-integration-client 0.0.2rc1__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 (29) hide show
  1. aws_elasticache_integration_client-0.0.2rc1/LICENSE +201 -0
  2. aws_elasticache_integration_client-0.0.2rc1/MANIFEST.in +2 -0
  3. aws_elasticache_integration_client-0.0.2rc1/PKG-INFO +264 -0
  4. aws_elasticache_integration_client-0.0.2rc1/README.md +239 -0
  5. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/__init__.py +48 -0
  6. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/auth.py +94 -0
  7. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/client.py +259 -0
  8. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/config_policy.py +27 -0
  9. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/connection.py +869 -0
  10. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/connection_manager.py +413 -0
  11. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/exceptions.py +101 -0
  12. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/hooks.py +254 -0
  13. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/idempotency.py +24 -0
  14. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/idempotent-operations.json +30 -0
  15. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/models.py +46 -0
  16. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/predicates.py +182 -0
  17. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/protocol.py +220 -0
  18. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/reconnect_policy.py +78 -0
  19. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/refresh.py +95 -0
  20. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/resp.py +237 -0
  21. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client/session.py +390 -0
  22. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client.egg-info/PKG-INFO +264 -0
  23. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client.egg-info/SOURCES.txt +26 -0
  24. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client.egg-info/dependency_links.txt +1 -0
  25. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client.egg-info/requires.txt +16 -0
  26. aws_elasticache_integration_client-0.0.2rc1/aws_elasticache_integration_client.egg-info/top_level.txt +1 -0
  27. aws_elasticache_integration_client-0.0.2rc1/pyproject.toml +80 -0
  28. aws_elasticache_integration_client-0.0.2rc1/setup.cfg +4 -0
  29. aws_elasticache_integration_client-0.0.2rc1/setup.py +34 -0
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,2 @@
1
+ # The tests need fixtures the sdist does not carry (tests/mock.py), so leave them out.
2
+ prune tests
@@ -0,0 +1,264 @@
1
+ Metadata-Version: 2.4
2
+ Name: aws-elasticache-integration-client
3
+ Version: 0.0.2rc1
4
+ Summary: ElastiCache Integrations for AWS SDK for Python (Boto3) DynamoDB clients.
5
+ License: Apache-2.0
6
+ Project-URL: Repository, https://github.com/awslabs/aws-elasticache-integration-client
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: boto3<2,>=1.43
11
+ Requires-Dist: botocore<2,>=1.43
12
+ Requires-Dist: cel-python>=0.1
13
+ Requires-Dist: developer-toolkit-elasticache<2,>=1.1
14
+ Provides-Extra: test
15
+ Requires-Dist: pytest>=7; extra == "test"
16
+ Requires-Dist: pytest-cov>=4; extra == "test"
17
+ Requires-Dist: cryptography>=42; extra == "test"
18
+ Requires-Dist: packaging>=24; extra == "test"
19
+ Provides-Extra: dev
20
+ Requires-Dist: ruff==0.17.3; extra == "dev"
21
+ Requires-Dist: mypy==2.4.1; extra == "dev"
22
+ Requires-Dist: build==1.6.1; extra == "dev"
23
+ Requires-Dist: twine==7.0.0; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ # ElastiCacheIntegrations (Python client)
27
+
28
+
29
+ ## Install & test
30
+
31
+ ```bash
32
+ cd python
33
+ pip install -e '.[test]' # runtime deps plus pytest and TLS test fixtures
34
+ python -m pytest # see tests/README.md for details
35
+ pip install -e '.[dev]' # pinned ruff, mypy, build, twine
36
+ ruff format --check . && ruff check . && mypy
37
+ ```
38
+
39
+ Runtime requires Python ≥ 3.10. See [`tests/README.md`](tests/README.md) for the test layout and
40
+ how to run the unit vs. end-to-end tests.
41
+
42
+ ## Releases
43
+
44
+ Python publication is driven by annotated Git tags. Stable releases use
45
+ `vMAJOR.MINOR.PATCH`; release candidates use `vMAJOR.MINOR.PATCH-rc.N`, which maps to the
46
+ PEP 440 version `MAJOR.MINOR.PATCHrcN`. A release tag applies to every language client: Node,
47
+ Python, and Java release together.
48
+
49
+ The tag is the release version source of truth. The `Python Release` workflow
50
+ converts it to PEP 440 form and stamps `pyproject.toml` only in its temporary
51
+ checkout, leaving the checked-in version at its local development baseline. It
52
+ runs the reusable Python CI workflow, builds one wheel and one source
53
+ distribution, and smoke tests the wheel on Python 3.10, 3.12, and 3.14 before
54
+ waiting for approval from the protected `release` environment and publishing
55
+ with PyPI trusted publishing and attestations. The workflow verifies the
56
+ published version and attaches the distributions plus `python-SHA256SUMS` to
57
+ the matching GitHub Release.
58
+
59
+ The PyPI distribution name is `aws-elasticache-integration-client`, and the import package is
60
+ `aws_elasticache_integration_client`. The PyPI project must
61
+ configure `.github/workflows/python-release.yml` as its trusted publisher for the `release`
62
+ environment. No PyPI token is used by the workflow. A manual workflow run performs the same test,
63
+ packaging, artifact validation, and wheel smoke stages for an optional version
64
+ without entering the release environment or publishing to PyPI.
65
+
66
+ ## Current state
67
+
68
+ The library delivers the happy path: intercept → serialize → `aws.config` handshake →
69
+ `aws.request` → return the cached response over a real TLS RESP3 connection, with
70
+ session-level IAM auth. The transport runs on a **pure-Python RESP3 connector**
71
+ (`ElastiCacheIntegrationsConnector`) — no Glide or other native dependency.
72
+ Its per-request timeout defaults to 5000 ms and can be changed with the
73
+ `cache_request_timeout` field (see below).
74
+
75
+ Cache requests may complete out of order when the cache returns a request ID and later delivers
76
+ the result in a `aws.response` RESP3 push. Deferred requests do not block later FIFO replies. If a
77
+ deferred request times out, only that request is abandoned, and a late push for its ID is dropped.
78
+ A timeout while a request is still FIFO-correlated closes the connection to prevent reply
79
+ misrouting. A RESP3 push with an unrecognized kind is treated as protocol corruption and closes
80
+ the connection. One connection sends at most 100 requests awaiting replies at once. Additional
81
+ callers wait for a slot within their `cache_request_timeout` instead of failing at the concurrency
82
+ boundary. Queue admission uses at most 75% of that timeout, reserving 25% to send and receive a
83
+ reply. If that budget is exhausted, the request is not sent to the cache and continues to origin
84
+ regardless of operation idempotency.
85
+
86
+ ## Installing into a client
87
+
88
+ `install()` takes a boto3 client the application already built, so the client keeps its own
89
+ profile, `botocore.config.Config`, endpoint and everything else, and its region and credentials
90
+ are the ones the cache is authenticated with.
91
+
92
+ ```python
93
+ import boto3
94
+ import aws_elasticache_integration_client
95
+
96
+ ddb = boto3.client("dynamodb", region_name="us-east-1")
97
+
98
+ aws_elasticache_integration_client.install(
99
+ client=ddb, endpoint="my-cache:6379", cache_name="my-cache"
100
+ )
101
+
102
+ ddb.get_item(TableName="my-table", Key={"id": {"S": "1"}}) # unchanged
103
+ ```
104
+
105
+ | Argument | Default | Meaning |
106
+ |---|---|---|
107
+ | `client` | required | The boto3 client to route through the cache. |
108
+ | `endpoint` | required | Cache endpoint as `host:port`. |
109
+ | `cache_name` | required | The ElastiCache Serverless cache name. |
110
+ | `user_id` | `default.iam-user` | ElastiCache IAM user id. |
111
+ | `verify` | `True` | Verify the cache's TLS certificate. `False` is for self-signed test rigs only. |
112
+ | `ca_certs` | `None` | CA bundle for the cache's certificate, instead of the system trust store. |
113
+ | `client_configuration` | all defaults | See [Configuration](#configuration). |
114
+
115
+ Everything above describes the connection to the **cache**, which the boto3 client knows nothing
116
+ about. TLS to AWS, and everything else about reaching the service, stays the client's own
117
+ configuration.
118
+
119
+ Closing the client disconnects the cache first, then closes the client as usual. A client can
120
+ have the cache installed once; a second `install()` on the same client raises
121
+ `ElastiCacheIntegrationsConfigError`.
122
+
123
+ ## Configuration
124
+
125
+ Optional ElastiCacheIntegrations settings go in one `aws_elasticache_integration_client.ElastiCacheIntegrationsClientConfiguration`, passed as
126
+ `client_configuration`. Every field has a default, so set only what you change. Cache policy
127
+ settings are sent to the cache through `aws.config`.
128
+
129
+ ```python
130
+ aws_elasticache_integration_client.install(
131
+ client=ddb,
132
+ endpoint="my-cache:6379",
133
+ cache_name="my-cache",
134
+ client_configuration=aws_elasticache_integration_client.ElastiCacheIntegrationsClientConfiguration(
135
+ cache_request_timeout=2000,
136
+ connection_timeout=5000,
137
+ fallback_duration=60,
138
+ cache_policy_overrides={"cached_tables": ["Users", "Sessions"]},
139
+ iam_token_refresh_delay=300,
140
+ ),
141
+ )
142
+ ```
143
+
144
+ | Field | Default | Meaning |
145
+ |---|---|---|
146
+ | `cache_request_timeout` | 5000 ms | How long to wait for each ElastiCacheIntegrations request's reply. |
147
+ | `connection_timeout` | 5000 ms | How long to try at startup, and how long a request waits for reconnection after a connection is lost. |
148
+ | `fallback_duration` | `None` (indefinite) | How long requests may go to the origin service while there is no cache connection (see below). |
149
+ | `cache_policy_overrides` | `None` | Settings that change what ElastiCacheIntegrations caches: `cached_tables` and `cached_operations` allowlists, and the cache entry lifetimes. See below. |
150
+ | `cache_policy_timeout` | 3600 s | How long ElastiCacheIntegrations may use a cache policy without confirmation from the cache. |
151
+ | `iam_token_refresh_delay` | 300 s | When the IAM toolkit signs a replacement token in the background. |
152
+
153
+ Building `ElastiCacheIntegrationsClientConfiguration` raises `ElastiCacheIntegrationsConfigError` for a value that is not usable.
154
+
155
+ ### Cache policy overrides
156
+
157
+ `cached_tables` and `cached_operations` are **allowlists**, and they intersect: only those
158
+ operations, on only those tables. Each one empty or absent means everything, so the example
159
+ above caches `Users` and `Sessions` and nothing else. There is no exclude form — to keep one
160
+ table out of the cache, name the tables that should be in it.
161
+
162
+ Lifetimes are set per category (`item_ttl`, `item_negative_ttl`, `query_ttl`, `scan_ttl`),
163
+ connection-wide at the top level or per table under `table_overrides`; a `table_overrides`
164
+ entry is settings only and never puts a table in scope.
165
+
166
+ ```python
167
+ cache_policy_overrides = {
168
+ "cached_tables": ["Users", "Sessions"],
169
+ "cached_operations": ["GetItem", "Query"],
170
+ "item_ttl": 500,
171
+ "item_negative_ttl": 0, # do not cache "this item does not exist"
172
+ "table_overrides": {"Users": {"item_ttl": 60}},
173
+ }
174
+ ```
175
+
176
+ A value the cache does not allow is refused at connect time with
177
+ `ElastiCacheIntegrationsOverridesRejected`, rather than being quietly adjusted. A field name
178
+ the cache does not recognise is **ignored**, so a typo fails silently — the names above are
179
+ the whole set.
180
+
181
+ ## IAM authentication
182
+
183
+ IAM token generation and refresh come from the Amazon ElastiCache developer toolkit, the
184
+ [`developer-toolkit-elasticache`](https://pypi.org/project/developer-toolkit-elasticache/) package on PyPI.
185
+ The toolkit validates and lowercases cache names and user IDs, re-reads the credentials for
186
+ every newly signed token, and owns the SigV4 signing contract. ElastiCacheIntegrations sends the bearer token
187
+ only in the TLS-protected `HELLO 3 AUTH` exchange; origin request signing remains owned by boto3.
188
+
189
+ The credentials are the ones behind the boto3 client, so the cache is authenticated as the same
190
+ principal as the requests, and rotation (SSO, assume-role, container, instance metadata) keeps
191
+ working because the credentials object refreshes itself. A client built with
192
+ `signature_version=UNSIGNED` carries none and is rejected.
193
+
194
+ `install()` creates a toolkit token manager. It caches the current token, signs a
195
+ replacement in the background after 300 seconds by default, and force-refreshes when a live
196
+ connection explicitly rejects the cached token. Set `iam_token_refresh_delay` to customize that
197
+ background signing point through `ElastiCacheIntegrationsClientConfiguration`; it must be greater than 0 and less
198
+ than 880 seconds, preserving the toolkit's 20-second safety margin on the 15-minute token.
199
+
200
+ Independently, ElastiCacheIntegrations sends `AUTH` on the live connection every 15 minutes to refresh the proxy's
201
+ forward-access session. A rejected background `AUTH` leaves the existing connection alive on its
202
+ previous authentication and is retried with backoff. Only a timeout or unexpected reply closes the
203
+ connection for FIFO safety. Closing the boto3 client stops both ElastiCacheIntegrations re-authentication and the
204
+ toolkit's token refresh.
205
+
206
+ ## Reconnection and fallback
207
+
208
+ A lost connection is rebuilt in the background and retried until it succeeds. Right after the
209
+ loss, a request waits up to `connection_timeout` for the new connection. If the connection is not
210
+ back by then, the AWS SDK sends the request to the origin service using the application's own
211
+ credentials. The same timeout bounds startup; client creation fails if no connection is ready.
212
+
213
+ How long requests may fall back, counted from the end of `connection_timeout`, is controlled by
214
+ `fallback_duration`:
215
+
216
+ | `fallback_duration` | Behavior |
217
+ |---|---|
218
+ | `None` (default), or negative | Serve from the origin service indefinitely, so a cache outage never becomes an application outage. |
219
+ | `N > 0` | Serve from the origin service for N seconds, then raise `ElastiCacheIntegrationsCacheUnavailable`. |
220
+ | `0` | Never fall back — wait up to `connection_timeout` for a connection, then raise `ElastiCacheIntegrationsCacheUnavailable`. |
221
+
222
+ The window is **per outage, not a total budget**: `fallback_duration=60` allows 60 seconds of
223
+ fallback each time the connection is lost, and a connection that keeps flapping gets a fresh 60
224
+ seconds after every successful reconnect.
225
+
226
+ `aws_elasticache_integration_client.ElastiCacheIntegrationsCacheUnavailable` subclasses botocore's `ConnectionClosedError`, so it is retryable and
227
+ an application's existing `except botocore...` blocks already catch it. Retryable cuts both ways:
228
+ under the SDK's default retry mode a raised request is retried, which is usually what you want — a
229
+ retry after backoff can land once the connection is back. With `fallback_duration=0`, a routed
230
+ request waits only for the part of `connection_timeout` left in the current outage. Later retries in
231
+ the same outage do not restart that wait.
232
+
233
+ When there is no live cache connection, the request has not been sent and can safely pass through
234
+ for any operation while the fallback window remains open. After a request is sent, origin fallback
235
+ is allowed only when the connection drops and the operation is in the shared replay-safe catalog.
236
+ While the connection remains healthy, `ORIGIN_ERROR` becomes a botocore-retryable error only for a
237
+ cataloged operation. `AUTH_ERROR` closes the stale connection and passes the rejected
238
+ request through while reconnection obtains fresh authentication. With `fallback_duration=0`, the
239
+ rejected request raises `ElastiCacheIntegrationsCacheUnavailable` at once instead. Other RESP
240
+ errors, malformed replies, and failures for non-idempotent operations propagate without origin
241
+ fallback.
242
+
243
+ ## Cache policy timeout
244
+
245
+ ElastiCacheIntegrations automatically confirms the resolved cache policy in the background through `aws.config`.
246
+ A new policy replaces the current one. An unchanged reply confirms that the current policy is still
247
+ valid. Both replies restart the timeout.
248
+
249
+ If confirmation fails, ElastiCacheIntegrations keeps using the last confirmed policy. That tolerance is bounded by
250
+ `cache_policy_timeout`, one hour by default. After the timeout, the next failed confirmation drops
251
+ the connection so a replacement can fetch a current policy. Requests follow the `fallback_duration`
252
+ rules while the connection is being replaced.
253
+
254
+ ## Next steps:
255
+
256
+ - **Observability.** Reconnection and config staleness are logged but emit no metrics, so under the
257
+ default `fallback_duration` a cache outage has no symptom other than the origin service's bill.
258
+ - **Detecting a silently dead peer.** A peer that vanishes without closing the socket is noticed only
259
+ when the next request times out. Closing that gap needs a periodic health check.
260
+ - **IAM authentication validation.** Exercise the toolkit-backed flow against a real IAM-enabled
261
+ cache in addition to the hermetic mock-cache coverage.
262
+ - **Public TTL / NTTL controls.** TTL/NTTL policy is resolved server-side from the
263
+ `aws.config` overrides; the public API does not expose per-table or per-request TTL
264
+ overrides yet.