-
Notifications
You must be signed in to change notification settings - Fork 0
/
simplebucket.js
139 lines (117 loc) · 4.41 KB
/
simplebucket.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const {S3, GetObjectCommand, PutObjectCommand, CreateBucketCommand} = require('@aws-sdk/client-s3');
/*
Utility class to retrieve the image of the graph representing the latest data.
Will return blank string if the bucket does not exist, or is empty, or if the
current image graph in the bucket is stale.
An image can be generated external to this utility and stored. The stored
image will use the date that represents the most recent valid data.
The date will increment after 6:00 PM PT so the image will need to be
regenerated at that point as the previous image will then be stale.
Improvement for this utility will be to expose the metadata and allow the
caller to decide if the image should be used and/or overwritten.
*/
class SimpleBucket {
#image;
#imageDate;
#client;
#bucketParams;
#bucketMetadata;
#bucketExists = false;
constructor(region, name, key) {
this.#client = new S3({region: region});
this.#imageDate = this.#getTodaysImageDate();
this.#bucketParams = {
Bucket: name,
Key: key
};
this.#bucketMetadata = {
// set image date to string 'yyyy-mm-dd'
// AWS metadata keys are lowercase
'imagedate': this.#imageDate.toLocaleString().split(',')[0]
}
}
/*
Returns the Date associated with the bucket. Used to determine
whether the image is valid and should be returned.
*/
getImageDate() {
return this.#imageDate;
}
/*
Get the latest base 64 encoded image data from the bucket.
Returns blank string if the bucket does not exist or if the image in the
bucket does not have today's date.
May raise an exception if there is an error retrieving the bucket.
*/
async getImage() {
try {
let imageBucket = await this.#getImageBucket()
this.#bucketExists = true;
if (imageBucket.Metadata && imageBucket.Metadata.imagedate === this.#bucketMetadata.imagedate) {
return await imageBucket.Body.transformToString();
}
} catch (error) {
// instanceof here doesn't work
if (error.name !== 'NoSuchBucket' && error.name !== 'NoSuchKey') {
throw error;
}
}
return '';
}
/*
Expects a base 64 encoded image and stores it in the bucket with
'imageDate' in the metadata, returns the HTTP Response code 200
if the storage operation is completed successfully.
*/
async storeImage(imageData) {
return await this.#storeLatestImage(imageData);
}
/*
Returns a Data object adjusted for report publication datetime
- the report is published after about 5:00 PM PT
- previous date is returned if it's currently before 6:00 PM PT
*/
#getTodaysImageDate() {
// parsing the date to vancouver time as the lambda function
// runs in a different timezone
let imageDate = new Date();
const dateOptions = {
hour12: false,
timeZone: 'America/Vancouver'
}
let currentDateTime = imageDate.toLocaleString("en-US", dateOptions);
const currentHour = currentDateTime.split(',')[1].split(":")[0].trim();
if (currentHour < 18) {
// no new data for today - let's use yesterday's image
imageDate.setDate(imageDate.getDate() - 1);
}
return imageDate;
}
/*
Create or update the bucket with the base 64 encoded image data using
today's date in the metadata.
*/
async #storeLatestImage(imageData) {
const bucketParams = this.#bucketParams;
bucketParams.Body = imageData;
bucketParams.ContentEncoding = 'base64';
bucketParams.Metadata = this.#bucketMetadata;
let bucketCommand = null;
if (!this.#bucketExists) {
bucketCommand = new CreateBucketCommand(bucketParams)
}
else {
bucketCommand = new PutObjectCommand(bucketParams);
}
const getObjectResult = await this.#client.send(bucketCommand);
return getObjectResult.$metadata.httpStatusCode;
}
/*
Gets the image bucket or empty string if it does not exist
*/
async #getImageBucket() {
let getObjectResult = await this.#client.send(new GetObjectCommand(this.#bucketParams));
return await getObjectResult;
}
}
module.exports = SimpleBucket;