Skip to content

Commit 28541c2

Browse files
authored
fix: infinite TTLs are not supported anymore, forward ttl=0 (#170)
* fix: infinite TTLs are not supported * fix add doc hook * fix e2e tests * forward ttl=0 to server, but bring back e2e test checking that ttl=0 should default
1 parent 94e34ad commit 28541c2

File tree

7 files changed

+174
-63
lines changed

7 files changed

+174
-63
lines changed

doc/api.md

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
</dd>
77
</dl>
88

9-
## Functions
9+
## Members
1010

1111
<dl>
12-
<dt><a href="#validate">validate(schema, data)</a> ⇒ <code>object</code></dt>
13-
<dd><p>Validates json according to a schema.</p>
14-
</dd>
15-
<dt><a href="#handleResponse">handleResponse(response, params)</a> ⇒ <code>void</code></dt>
16-
<dd><p>Handle a network response.</p>
12+
<dt><a href="#MAX_TTL">MAX_TTL</a> : <code>number</code></dt>
13+
<dd><p>Max supported TTL, 365 days in seconds</p>
1714
</dd>
15+
</dl>
16+
17+
## Functions
18+
19+
<dl>
1820
<dt><a href="#init">init([config])</a> ⇒ <code><a href="#AdobeState">Promise.&lt;AdobeState&gt;</a></code></dt>
1921
<dd><p>Initializes and returns the key-value-store SDK.</p>
2022
<p>To use the SDK you must either provide your
@@ -159,31 +161,12 @@ for await (const { keys } of state.list({ match: 'abc*' })) {
159161
console.log(keys)
160162
}
161163
```
162-
<a name="validate"></a>
163-
164-
## validate(schema, data) ⇒ <code>object</code>
165-
Validates json according to a schema.
166-
167-
**Kind**: global function
168-
**Returns**: <code>object</code> - the result
164+
<a name="MAX_TTL"></a>
169165

170-
| Param | Type | Description |
171-
| --- | --- | --- |
172-
| schema | <code>object</code> | the AJV schema |
173-
| data | <code>object</code> | the json data to test |
174-
175-
<a name="handleResponse"></a>
176-
177-
## handleResponse(response, params) ⇒ <code>void</code>
178-
Handle a network response.
179-
180-
**Kind**: global function
181-
182-
| Param | Type | Description |
183-
| --- | --- | --- |
184-
| response | <code>Response</code> | a fetch Response |
185-
| params | <code>object</code> | the params to the network call |
166+
## MAX\_TTL : <code>number</code>
167+
Max supported TTL, 365 days in seconds
186168

169+
**Kind**: global variable
187170
<a name="init"></a>
188171

189172
## init([config]) ⇒ [<code>Promise.&lt;AdobeState&gt;</code>](#AdobeState)
@@ -227,7 +210,7 @@ AdobeState put options
227210

228211
| Name | Type | Description |
229212
| --- | --- | --- |
230-
| ttl | <code>number</code> | time-to-live for key-value pair in seconds, defaults to 24 hours (86400s). Set to < 0 for max ttl of one year. A value of 0 sets default. |
213+
| ttl | <code>number</code> | Time-To-Live for key-value pair in seconds. When not defined or set to 0, defaults to 24 hours (86400s). Max TTL is one year (31536000s), `require('@adobe/aio-lib-state').MAX_TTL`. A TTL of 0 defaults to 24 hours. |
231214

232215
<a name="AdobeStateGetReturnValue"></a>
233216

e2e/e2e.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,20 @@ describe('e2e tests using OpenWhisk credentials (as env vars)', () => {
113113

114114
// 3. test max ttl
115115
const nowPlus365Days = new Date(MAX_TTL_SECONDS).getTime()
116-
expect(await state.put(testKey, testValue, { ttl: -1 })).toEqual(testKey)
116+
expect(await state.put(testKey, testValue, { ttl: MAX_TTL_SECONDS })).toEqual(testKey)
117117
res = await state.get(testKey)
118118
resTime = new Date(res.expiration).getTime()
119-
expect(resTime).toBeGreaterThanOrEqual(nowPlus365Days)
119+
expect(resTime).toBeGreaterThanOrEqual(nowPlus365Days - 10000)
120120

121121
// 4. test that after ttl object is deleted
122122
expect(await state.put(testKey, testValue, { ttl: 2 })).toEqual(testKey)
123123
res = await state.get(testKey)
124124
expect(new Date(res.expiration).getTime()).toBeLessThanOrEqual(new Date(Date.now() + 2000).getTime())
125125
await waitFor(3000) // give it one more sec - ttl is not so precise
126126
expect(await state.get(testKey)).toEqual(undefined)
127+
128+
// 5. infinite ttl not supported
129+
await expect(state.put(testKey, testValue, { ttl: -1 })).rejects.toThrow()
127130
})
128131

129132
test('listKeys test: few < 128 keys, many, and expired entries', async () => {

index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2019 Adobe. All rights reserved.
2+
Copyright 2024 Adobe. All rights reserved.
33
This file is licensed to you under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License. You may obtain a copy
55
of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -9,5 +9,13 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
99
OF ANY KIND, either express or implied. See the License for the specific language
1010
governing permissions and limitations under the License.
1111
*/
12+
const { MAX_TTL_SECONDS } = require('./lib/constants')
1213
require('./lib/AdobeState')
14+
1315
module.exports = require('./lib/init')
16+
17+
/**
18+
* Max supported TTL, 365 days in seconds
19+
* @type {number}
20+
*/
21+
module.exports.MAX_TTL = MAX_TTL_SECONDS

lib/AdobeState.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ const {
2828
MAX_LIST_COUNT_HINT,
2929
REQUEST_ID_HEADER,
3030
MIN_LIST_COUNT_HINT,
31-
REGEX_PATTERN_LIST_KEY_MATCH
31+
REGEX_PATTERN_LIST_KEY_MATCH,
32+
MAX_TTL_SECONDS
3233
} = require('./constants')
3334

3435
/* *********************************** typedefs *********************************** */
@@ -48,8 +49,10 @@ const {
4849
*
4950
* @typedef AdobeStatePutOptions
5051
* @type {object}
51-
* @property {number} ttl time-to-live for key-value pair in seconds, defaults to 24 hours (86400s). Set to < 0 for max ttl of one year. A
52-
* value of 0 sets default.
52+
* @property {number} ttl Time-To-Live for key-value pair in seconds. When not
53+
* defined or set to 0, defaults to 24 hours (86400s). Max TTL is one year
54+
* (31536000s), `require('@adobe/aio-lib-state').MAX_TTL`. A TTL of 0 defaults
55+
* to 24 hours.
5356
*/
5457

5558
/**
@@ -69,6 +72,7 @@ const {
6972
* @param {object} schema the AJV schema
7073
* @param {object} data the json data to test
7174
* @returns {object} the result
75+
* @private
7276
*/
7377
function validate (schema, data) {
7478
const ajv = new Ajv({ allErrors: true })
@@ -78,7 +82,7 @@ function validate (schema, data) {
7882
return { valid, errors: validate.errors }
7983
}
8084

81-
// eslint-disable-next-line jsdoc/require-jsdoc
85+
/** @private */
8286
async function _wrap (promise, params) {
8387
let response
8488
try {
@@ -97,6 +101,7 @@ async function _wrap (promise, params) {
97101
* @param {Response} response a fetch Response
98102
* @param {object} params the params to the network call
99103
* @returns {void}
104+
* @private
100105
*/
101106
async function handleResponse (response, params) {
102107
if (response.ok) {
@@ -317,20 +322,31 @@ class AdobeState {
317322
},
318323
value: {
319324
type: 'string'
325+
},
326+
ttl: {
327+
type: 'integer'
320328
}
321329
}
322330
}
323331

324-
const { valid, errors } = validate(schema, { key, value })
332+
// validation
333+
const { ttl } = options
334+
const { valid, errors } = validate(schema, { key, value, ttl })
325335
if (!valid) {
326336
logAndThrow(new codes.ERROR_BAD_ARGUMENT({
327337
messageValues: utils.formatAjvErrors(errors),
328-
sdkDetails: { key, value, options, errors }
338+
sdkDetails: { key, valueLength: value.length, options, errors }
339+
}))
340+
}
341+
if (ttl !== undefined && (ttl < 0 || ttl > MAX_TTL_SECONDS)) {
342+
// error message is nicer like this than for
343+
logAndThrow(new codes.ERROR_BAD_ARGUMENT({
344+
messageValues: 'ttl must be <= 365 days (31536000s). Infinite TTLs (< 0) are not supported.',
345+
sdkDetails: { key, valueLength: value.length, options }
329346
}))
330347
}
331348

332-
const { ttl } = options
333-
const queryParams = ttl ? { ttl } : {}
349+
const queryParams = ttl !== undefined ? { ttl } : {}
334350
const requestOptions = {
335351
method: 'PUT',
336352
headers: {

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
"e2e": "jest -c jest.e2e.config.js",
1616
"jsdoc": "jsdoc2md -f index.js 'lib/**/*.js' > doc/api.md",
1717
"typings": "jsdoc -t node_modules/tsd-jsdoc/dist -r lib -d . && replace-in-file /declare/g export types.d.ts --isRegex",
18-
"generate-docs": "npm run jsdoc && npm run typings"
18+
"generate-docs": "npm run jsdoc && npm run typings",
19+
"git-add-docs": "git add doc/ types.d.ts"
1920
},
2021
"pre-commit": [
21-
"generate-docs"
22+
"generate-docs",
23+
"git-add-docs"
2224
],
2325
"author": "Adobe Inc.",
2426
"license": "Apache-2.0",

0 commit comments

Comments
 (0)