Skip to content

Commit 8f7e008

Browse files
committed
Add product metadata and tags to S3 objects
- Add product ID as tag and product name as metadata when uploading images - Update StorageService to support metadata and tagging - Add helper functions for retrieving object metadata and tags - Update integration tests to validate metadata and tags are applied correctly Resolves #64
1 parent 0c3cf12 commit 8f7e008

3 files changed

Lines changed: 56 additions & 3 deletions

File tree

src/services/ProductService.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,15 @@ async function getProductImage(id) {
8888
async function uploadProductImage(id, buffer) {
8989
const client = await getClient();
9090

91-
await uploadFile(id, buffer);
91+
// Get product name for metadata
92+
const productResult = await client.query(
93+
"SELECT name FROM products WHERE id = $1",
94+
[id],
95+
);
96+
const productName =
97+
productResult.rows.length > 0 ? productResult.rows[0].name : "";
98+
99+
await uploadFile(id, buffer, productName);
92100
await client.query("UPDATE products SET has_image=TRUE WHERE id=$1", [id]);
93101
}
94102

src/services/StorageService.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ const {
22
S3Client,
33
PutObjectCommand,
44
GetObjectCommand,
5+
GetObjectTaggingCommand,
6+
HeadObjectCommand,
57
} = require("@aws-sdk/client-s3");
68
const { publishEvent } = require("./PublisherService");
79

@@ -25,14 +27,18 @@ async function getFile(id) {
2527
return result.Body;
2628
}
2729

28-
async function uploadFile(id, buffer) {
30+
async function uploadFile(id, buffer, productName) {
2931
const name = "product.png";
3032

3133
await s3Client.send(
3234
new PutObjectCommand({
3335
Bucket: BUCKET_NAME,
3436
Key: `${id}/${name}`,
3537
Body: buffer,
38+
Metadata: {
39+
productName: productName || "",
40+
},
41+
Tagging: `productId=${id}`,
3642
}),
3743
);
3844

@@ -47,7 +53,35 @@ async function uploadFile(id, buffer) {
4753
return details;
4854
}
4955

56+
async function getObjectMetadata(id) {
57+
const name = "product.png";
58+
59+
const result = await s3Client.send(
60+
new HeadObjectCommand({
61+
Bucket: BUCKET_NAME,
62+
Key: `${id}/${name}`,
63+
}),
64+
);
65+
66+
return result.Metadata;
67+
}
68+
69+
async function getObjectTags(id) {
70+
const name = "product.png";
71+
72+
const result = await s3Client.send(
73+
new GetObjectTaggingCommand({
74+
Bucket: BUCKET_NAME,
75+
Key: `${id}/${name}`,
76+
}),
77+
);
78+
79+
return result.TagSet;
80+
}
81+
5082
module.exports = {
5183
uploadFile,
5284
getFile,
85+
getObjectMetadata,
86+
getObjectTags,
5387
};

test/integration/productCreation.integration.spec.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const { KafkaConsumer } = require("./kafkaSupport");
99
describe("Product creation", () => {
1010
let postgresContainer, kafkaContainer, localstackContainer;
1111
let kafkaConsumer;
12-
let productService, publisherService;
12+
let productService, publisherService, storageService;
1313

1414
beforeAll(async () => {
1515
console.log("Starting containers");
@@ -30,6 +30,7 @@ describe("Product creation", () => {
3030
beforeAll(async () => {
3131
productService = require("../../src/services/ProductService");
3232
publisherService = require("../../src/services/PublisherService");
33+
storageService = require("../../src/services/StorageService");
3334
});
3435

3536
afterAll(async () => {
@@ -126,6 +127,16 @@ describe("Product creation", () => {
126127
}))();
127128

128129
expect(retrievedImageBuffer).toEqual(imageBuffer);
130+
131+
// Validate metadata
132+
const metadata = await storageService.getObjectMetadata(createdProduct.id);
133+
expect(metadata.productname).toBe("Kafka publishing test");
134+
135+
// Validate tags
136+
const tags = await storageService.getObjectTags(createdProduct.id);
137+
expect(tags).toEqual([
138+
{ Key: "productId", Value: createdProduct.id.toString() },
139+
]);
129140
}, 15000);
130141

131142
it("doesn't allow duplicate UPCs", async () => {

0 commit comments

Comments
 (0)