import { DeleteObjectCommand, GetObjectCommand, ListObjectsV2Command, S3Client, } from "@aws-sdk/client-s3"; import { WidgetRequestRetriever } from "."; import { WidgetRequest } from "@/shared/schema"; import { TracingLogger } from "@/consumer/log"; export class S3WidgetRequestRetriever implements WidgetRequestRetriever { static LIST_KEY_MAX = 1; private bucket: string; private s3Client: S3Client; private logger: TracingLogger; constructor(bucket: string, s3Client: S3Client, logger: TracingLogger) { this.bucket = bucket; this.s3Client = s3Client; this.logger = logger; } private async getWidgetRequest(key: string) { const getCommand = new GetObjectCommand({ Bucket: this.bucket, Key: key, }); const response = await this.s3Client.send(getCommand); const body = await response.Body?.transformToString(); if (body && body.length) return WidgetRequest.parse(JSON.parse(body)); } public async refreshRequests() { // ListObjectsV2 returns keys in ascending lexicographical order const listCommand = new ListObjectsV2Command({ MaxKeys: S3WidgetRequestRetriever.LIST_KEY_MAX, Bucket: this.bucket, }); const response = await this.s3Client.send(listCommand); const key = response.Contents && response.Contents[0]?.Key; if (!key) { this.logger.info(`No more keys in Bucket=(${this.bucket}).`); return []; } const widgetRequest = await this.getWidgetRequest(key); const deleteWidgetRequest = new DeleteObjectCommand({ Key: key, Bucket: this.bucket, }); await this.s3Client.send(deleteWidgetRequest); if (!widgetRequest) { this.logger.warn(`No valid widget at Key=(${key}).`); return []; } return [widgetRequest]; } }