Skip to content

Commit 21b0bf5

Browse files
committed
Added TTL for MI
1 parent f43e04f commit 21b0bf5

File tree

12 files changed

+53
-33
lines changed

12 files changed

+53
-33
lines changed

infrastructure/terraform/components/api/locals.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ locals {
2121
LETTERS_TABLE_NAME = aws_dynamodb_table.letters.name,
2222
MI_TABLE_NAME = aws_dynamodb_table.mi.name,
2323
LETTER_TTL_HOURS = 12960, # 18 months * 30 days * 24 hours
24+
MI_TTL_HOURS = 2160 # 90 days * 24 hours
2425
SUPPLIER_ID_HEADER = "nhsd-supplier-id",
2526
APIM_CORRELATION_HEADER = "nhsd-correlation-id",
2627
DOWNLOAD_URL_TTL_SECONDS = 60

internal/datastore/src/__test__/db.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export async function setupDynamoDBContainer() {
3131
endpoint,
3232
lettersTableName: 'letters',
3333
miTableName: 'management-info',
34-
ttlHours: 1
34+
lettersTtlHours: 1,
35+
miTtlHours: 1
3536
};
3637

3738
return {

internal/datastore/src/__test__/letter-repository.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ describe('LetterRepository', () => {
307307

308308
const mockSend = jest.fn().mockResolvedValue({ Items: null });
309309
const mockDdbClient = { send: mockSend } as any;
310-
const repo = new LetterRepository(mockDdbClient, { debug: jest.fn() } as any, { lettersTableName: 'letters', ttlHours: 1 });
310+
const repo = new LetterRepository(mockDdbClient, { debug: jest.fn() } as any, { lettersTableName: 'letters', lettersTtlHours: 1 });
311311

312312
const letters = await repo.getLettersBySupplier('supplier1', 'PENDING', 10);
313313
expect(letters).toEqual([]);

internal/datastore/src/__test__/mi-repository.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ describe('MiRepository', () => {
5959
id: expect.any(String),
6060
createdAt: '2020-02-01T00:00:00.000Z',
6161
updatedAt: '2020-02-01T00:00:00.000Z',
62+
ttl: 1580518800, // 2020-02-01T00:01:00.000Z, seconds since epoch
6263
...mi
6364
}));
6465
});

internal/datastore/src/config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export type DatastoreConfig = {
33
endpoint?: string,
44
lettersTableName: string,
55
miTableName: string,
6-
ttlHours: number
6+
lettersTtlHours: number,
7+
miTtlHours: number
78
}

internal/datastore/src/letter-repository.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const defaultPagingOptions = {
2323

2424
export type LetterRepositoryConfig = {
2525
lettersTableName: string,
26-
ttlHours: number
26+
lettersTtlHours: number
2727
}
2828

2929
export class LetterRepository {
@@ -37,7 +37,7 @@ export class LetterRepository {
3737
...letter,
3838
supplierStatus: `${letter.supplierId}#${letter.status}`,
3939
supplierStatusSk: new Date().toISOString(),
40-
ttl: Math.floor(Date.now() / 1000 + 60 * 60 * this.config.ttlHours)
40+
ttl: Math.floor(Date.now() / 1000 + 60 * 60 * this.config.lettersTtlHours)
4141
};
4242
try {
4343
await this.ddbClient.send(new PutCommand({
@@ -68,7 +68,7 @@ export class LetterRepository {
6868
...letter,
6969
supplierStatus: `${letter.supplierId}#${letter.status}`,
7070
supplierStatusSk: Date.now().toString(),
71-
ttl: Math.floor(Date.now() / 1000 + 60 * 60 * this.config.ttlHours)
71+
ttl: Math.floor(Date.now() / 1000 + 60 * 60 * this.config.lettersTtlHours)
7272
});
7373

7474
if (lettersDb.length === 25 || i === letters.length - 1) {
@@ -143,7 +143,7 @@ export class LetterRepository {
143143
':status': letterToUpdate.status,
144144
':updatedAt': new Date().toISOString(),
145145
':supplierStatus': `${letterToUpdate.supplierId}#${letterToUpdate.status}`,
146-
':ttl': Math.floor(Date.now() / 1000 + 60 * 60 * this.config.ttlHours)
146+
':ttl': Math.floor(Date.now() / 1000 + 60 * 60 * this.config.lettersTtlHours)
147147
};
148148

149149
if (letterToUpdate.reasonCode)

internal/datastore/src/mi-repository.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { Logger } from 'pino';
77
import { v4 as uuidv4 } from 'uuid';
88

99
export type MIRepositoryConfig = {
10-
miTableName: string
10+
miTableName: string,
11+
miTtlHours: number
1112
};
1213

1314
export class MIRepository {
@@ -16,14 +17,15 @@ export class MIRepository {
1617
readonly config: MIRepositoryConfig) {
1718
}
1819

19-
async putMI(mi: Omit<MI, 'id' | 'createdAt' | 'updatedAt'>): Promise<MI> {
20+
async putMI(mi: Omit<MI, 'id' | 'createdAt' | 'updatedAt' | 'ttl'>): Promise<MI> {
2021

2122
const now = new Date().toISOString();
2223
const miDb = {
2324
...mi,
2425
id: uuidv4(),
2526
createdAt: now,
26-
updatedAt: now
27+
updatedAt: now,
28+
ttl: Math.floor(Date.now() / 1000 + 60 * 60 * this.config.miTtlHours)
2729
};
2830

2931
await this.ddbClient.send(new PutCommand({

internal/datastore/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ export const MISchemaBase = z.object({
5959
export const MISchema = MISchemaBase.extend({
6060
supplierId: idRef(SupplierSchema),
6161
createdAt: z.string(),
62-
updatedAt: z.string()
62+
updatedAt: z.string(),
63+
ttl: z.int(),
6364
}).describe('MI');
6465

6566
export type MI = z.infer<typeof MISchema>;
Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11

2-
import { MIRepository } from '../../../../../internal/datastore/src';
32
import type { Deps } from '../deps';
43

54
describe('createDependenciesContainer', () => {
5+
6+
const env = {
7+
LETTERS_TABLE_NAME: 'LettersTable',
8+
LETTER_TTL_HOURS: 12960,
9+
MI_TABLE_NAME: 'MITable',
10+
MI_TTL_HOURS: 2160,
11+
SUPPLIER_ID_HEADER: 'nhsd-supplier-id',
12+
APIM_CORRELATION_HEADER: 'nhsd-correlation-id',
13+
DOWNLOAD_URL_TTL_SECONDS: 60
14+
};
15+
616
beforeEach(() => {
717
jest.clearAllMocks();
818
jest.resetModules();
@@ -29,22 +39,17 @@ describe('createDependenciesContainer', () => {
2939
}));
3040

3141
// Env
32-
jest.mock('../env', () => ({
33-
envVars: {
34-
LETTERS_TABLE_NAME: 'LettersTable',
35-
LETTER_TTL_HOURS: 12960,
36-
SUPPLIER_ID_HEADER: 'nhsd-supplier-id',
37-
APIM_CORRELATION_HEADER: 'nhsd-correlation-id',
38-
DOWNLOAD_URL_TTL_SECONDS: 60
39-
},
40-
}));
42+
jest.mock('../env', () => ({envVars: env}));
4143
});
4244

4345
test('constructs deps and wires repository config correctly', async () => {
4446
// get current mock instances
4547
const { S3Client } = jest.requireMock('@aws-sdk/client-s3') as { S3Client: jest.Mock };
4648
const pinoMock = jest.requireMock('pino') as { default: jest.Mock };
47-
const { LetterRepository } = jest.requireMock('../../../../../internal/datastore') as { LetterRepository: jest.Mock };
49+
const { LetterRepository, MIRepository } = jest.requireMock('../../../../../internal/datastore') as {
50+
LetterRepository: jest.Mock,
51+
MIRepository: jest.Mock
52+
};
4853

4954
const { createDependenciesContainer } = require('../deps');
5055
const deps: Deps = createDependenciesContainer();
@@ -53,18 +58,19 @@ describe('createDependenciesContainer', () => {
5358
expect(pinoMock.default).toHaveBeenCalledTimes(1);
5459

5560
expect(LetterRepository).toHaveBeenCalledTimes(1);
56-
const repoCtorArgs = (LetterRepository as jest.Mock).mock.calls[0];
57-
expect(repoCtorArgs[2]).toEqual({
61+
const letterRepoCtorArgs = (LetterRepository as jest.Mock).mock.calls[0];
62+
expect(letterRepoCtorArgs[2]).toEqual({
5863
lettersTableName: 'LettersTable',
59-
ttlHours: 12960
64+
lettersTtlHours: 12960
6065
});
6166

62-
expect(deps.env).toEqual({
63-
LETTERS_TABLE_NAME: 'LettersTable',
64-
LETTER_TTL_HOURS: 12960,
65-
SUPPLIER_ID_HEADER: 'nhsd-supplier-id',
66-
APIM_CORRELATION_HEADER: 'nhsd-correlation-id',
67-
DOWNLOAD_URL_TTL_SECONDS: 60
67+
expect(MIRepository).toHaveBeenCalledTimes(1);
68+
const miRepoCtorArgs = (MIRepository as jest.Mock).mock.calls[0];
69+
expect(miRepoCtorArgs[2]).toEqual({
70+
miTableName: 'MITable',
71+
miTtlHours: 2160
6872
});
73+
74+
expect(deps.env).toEqual(env);
6975
});
7076
});

lambdas/api-handler/src/config/__tests__/env.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ describe('lambdaEnv', () => {
1818
process.env.LETTERS_TABLE_NAME = 'letters-table';
1919
process.env.MI_TABLE_NAME = 'mi-table';
2020
process.env.LETTER_TTL_HOURS = '12960';
21+
process.env.MI_TTL_HOURS = '2160';
2122
process.env.DOWNLOAD_URL_TTL_SECONDS = '60';
2223
process.env.MAX_LIMIT = '2500';
2324

@@ -29,6 +30,7 @@ describe('lambdaEnv', () => {
2930
LETTERS_TABLE_NAME: 'letters-table',
3031
MI_TABLE_NAME: 'mi-table',
3132
LETTER_TTL_HOURS: 12960,
33+
MI_TTL_HOURS: 2160,
3234
DOWNLOAD_URL_TTL_SECONDS: 60,
3335
MAX_LIMIT: 2500,
3436
});
@@ -40,6 +42,7 @@ describe('lambdaEnv', () => {
4042
process.env.LETTERS_TABLE_NAME = undefined; // simulate missing var
4143
process.env.MI_TABLE_NAME = 'mi-table';
4244
process.env.LETTER_TTL_HOURS = '12960';
45+
process.env.MI_TTL_HOURS = '2160';
4346
process.env.DOWNLOAD_URL_TTL_SECONDS = '60';
4447

4548
expect(() => require('../env')).toThrow(ZodError);
@@ -51,6 +54,7 @@ describe('lambdaEnv', () => {
5154
process.env.LETTERS_TABLE_NAME = 'letters-table';
5255
process.env.MI_TABLE_NAME = 'mi-table';
5356
process.env.LETTER_TTL_HOURS = '12960';
57+
process.env.MI_TTL_HOURS = '2160';
5458
process.env.DOWNLOAD_URL_TTL_SECONDS = '60';
5559

5660
const { envVars } = require('../env');
@@ -61,6 +65,7 @@ describe('lambdaEnv', () => {
6165
LETTERS_TABLE_NAME: 'letters-table',
6266
MI_TABLE_NAME: 'mi-table',
6367
LETTER_TTL_HOURS: 12960,
68+
MI_TTL_HOURS: 2160,
6469
DOWNLOAD_URL_TTL_SECONDS: 60,
6570
MAX_LIMIT: undefined
6671
});

0 commit comments

Comments
 (0)