@adtrackify/at-service-common 3.1.37 → 3.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/services/cache/product-cache-service.d.ts +2 -1
- package/dist/cjs/services/cache/product-cache-service.js +4 -2
- package/dist/cjs/services/cache/product-cache-service.js.map +1 -1
- package/dist/cjs/services/db/shopify-products-cache-db-service.d.ts +12 -5
- package/dist/cjs/services/db/shopify-products-cache-db-service.js +34 -33
- package/dist/cjs/services/db/shopify-products-cache-db-service.js.map +1 -1
- package/dist/cjs/services/shopify/products/shopify-products-serviceV2.d.ts +6 -1
- package/dist/cjs/services/shopify/products/shopify-products-serviceV2.js +21 -3
- package/dist/cjs/services/shopify/products/shopify-products-serviceV2.js.map +1 -1
- package/dist/esm/services/cache/product-cache-service.d.ts +2 -1
- package/dist/esm/services/cache/product-cache-service.js +4 -2
- package/dist/esm/services/cache/product-cache-service.js.map +1 -1
- package/dist/esm/services/db/shopify-products-cache-db-service.d.ts +12 -5
- package/dist/esm/services/db/shopify-products-cache-db-service.js +32 -34
- package/dist/esm/services/db/shopify-products-cache-db-service.js.map +1 -1
- package/dist/esm/services/shopify/products/shopify-products-serviceV2.d.ts +6 -1
- package/dist/esm/services/shopify/products/shopify-products-serviceV2.js +21 -3
- package/dist/esm/services/shopify/products/shopify-products-serviceV2.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,7 +10,8 @@ export interface ProductCache extends GenericCachedObject {
|
|
|
10
10
|
export declare const getProductCacheKey: (pixelId: string, productId: string) => string;
|
|
11
11
|
export declare class ProductCacheService {
|
|
12
12
|
private genericCacheService;
|
|
13
|
-
|
|
13
|
+
private redisCacheTtlInSeconds;
|
|
14
|
+
constructor(cacheLambdaFunctionArn: string, redisCacheTtlInSeconds: number);
|
|
14
15
|
getCacheKey: (pixelId: string, productId: string) => string;
|
|
15
16
|
getProductFromCache: (pixelId: string, productId: string) => Promise<InternalProduct | undefined>;
|
|
16
17
|
getProductCache: (pixelId: string, productId: string) => Promise<ProductCache | undefined>;
|
|
@@ -15,8 +15,10 @@ const getProductCacheKey = (pixelId, productId) => {
|
|
|
15
15
|
exports.getProductCacheKey = getProductCacheKey;
|
|
16
16
|
class ProductCacheService {
|
|
17
17
|
genericCacheService;
|
|
18
|
-
|
|
18
|
+
redisCacheTtlInSeconds;
|
|
19
|
+
constructor(cacheLambdaFunctionArn, redisCacheTtlInSeconds) {
|
|
19
20
|
this.genericCacheService = new generic_cache_service_1.GenericCacheService(cacheLambdaFunctionArn);
|
|
21
|
+
this.redisCacheTtlInSeconds = redisCacheTtlInSeconds || DEFAULT_TTL_IN_SECONDS;
|
|
20
22
|
}
|
|
21
23
|
getCacheKey = (pixelId, productId) => {
|
|
22
24
|
return (0, exports.getProductCacheKey)(pixelId, productId);
|
|
@@ -36,7 +38,7 @@ class ProductCacheService {
|
|
|
36
38
|
};
|
|
37
39
|
putProductInCache = async (pixelId, productId, product, ttlInSeconds) => {
|
|
38
40
|
const cacheKey = this.getCacheKey(pixelId, productId);
|
|
39
|
-
const ttl = ttlInSeconds ||
|
|
41
|
+
const ttl = ttlInSeconds || this.redisCacheTtlInSeconds;
|
|
40
42
|
const expiresAt = luxon_1.DateTime.utc().plus({ seconds: ttl }).toSeconds();
|
|
41
43
|
const cachedAtEpoch = luxon_1.DateTime.utc().toSeconds();
|
|
42
44
|
const fullSha256 = crypto_1.default.createHash('sha256').update(JSON.stringify(product)).digest('hex');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-cache-service.js","sourceRoot":"","sources":["../../../../src/services/cache/product-cache-service.ts"],"names":[],"mappings":";;;;;;AAAA,iCAAiC;AACjC,oEAA+D;AAE/D,qCAA0D;AAE1D,oDAA4B;AAE5B,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAUtC,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAE,SAAiB,EAAE,EAAE;IACvE,OAAO,oBAAoB,OAAO,IAAI,SAAS,EAAE,CAAC;AACpD,CAAC,CAAA;AAFY,QAAA,kBAAkB,sBAE9B;AAED,MAAa,mBAAmB;IACtB,mBAAmB,CAAsB;
|
|
1
|
+
{"version":3,"file":"product-cache-service.js","sourceRoot":"","sources":["../../../../src/services/cache/product-cache-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { InternalProduct } from '../shopify/types/product';
|
|
2
|
+
import { ProductCache } from '../cache';
|
|
3
|
+
export interface ShopifyProductDynamoDbCache extends ProductCache {
|
|
4
|
+
pixelId_productId: string;
|
|
5
|
+
pixelId: string;
|
|
6
|
+
productId: string;
|
|
7
|
+
}
|
|
2
8
|
export declare class ShopifyProductsCacheDbService {
|
|
3
9
|
TABLE_NAME: string;
|
|
4
10
|
KEY_NAME: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
private dynamoDbCacheTtlInSeconds;
|
|
12
|
+
constructor(tableName: string, keyName: string, dynamoDbCacheTtlInSeconds: number);
|
|
13
|
+
getProductFromDynamoDBCache: (pixelId: string, productId: string) => Promise<InternalProduct | undefined>;
|
|
14
|
+
putProductInDynamoDBCache: (pixelId: string, productId: string, product: InternalProduct, ttlInSeconds?: number) => Promise<import("@aws-sdk/lib-dynamodb").PutCommandOutput | null>;
|
|
15
|
+
private isProductCacheStale;
|
|
9
16
|
}
|
|
@@ -1,65 +1,66 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.ShopifyProductsCacheDbService = void 0;
|
|
4
7
|
const clients_1 = require("../../clients");
|
|
5
8
|
const libs_1 = require("../../libs");
|
|
6
9
|
const luxon_1 = require("luxon");
|
|
7
10
|
const helpers_1 = require("../../helpers");
|
|
11
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
12
|
+
const DEFAULT_TTL_IN_SECONDS = 7 * 24 * 3600;
|
|
8
13
|
class ShopifyProductsCacheDbService {
|
|
9
14
|
TABLE_NAME;
|
|
10
15
|
KEY_NAME;
|
|
11
|
-
|
|
16
|
+
dynamoDbCacheTtlInSeconds;
|
|
17
|
+
constructor(tableName, keyName, dynamoDbCacheTtlInSeconds) {
|
|
12
18
|
this.TABLE_NAME = tableName;
|
|
13
19
|
this.KEY_NAME = keyName;
|
|
20
|
+
this.dynamoDbCacheTtlInSeconds = dynamoDbCacheTtlInSeconds || DEFAULT_TTL_IN_SECONDS;
|
|
14
21
|
}
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const cachedShopifyProduct = await this.getShopifyProductFromCacheREST(pixelId, productId);
|
|
18
|
-
if (cachedShopifyProduct) {
|
|
19
|
-
return cachedShopifyProduct.product;
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
const productRes = await clients_1.ShopifyClient.getProductREST(shop, accessToken, productId);
|
|
23
|
-
if (productRes.status === 200 && productRes?.data?.product) {
|
|
24
|
-
const product = productRes.data.product;
|
|
25
|
-
await this.putShopifyProductCacheREST(pixelId, productId, product);
|
|
26
|
-
return product;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
helpers_1.Logger.error('Failed lookupShopifyProductCacheREST', { error });
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
getShopifyProductFromCacheREST = async (pixelId, productId) => {
|
|
22
|
+
getProductFromDynamoDBCache = async (pixelId, productId) => {
|
|
37
23
|
try {
|
|
38
24
|
const cachedProduct = await clients_1.DynamoDbClient.safeGet(this.TABLE_NAME, this.KEY_NAME, `${pixelId}_${productId}`);
|
|
39
|
-
if (cachedProduct) {
|
|
40
|
-
|
|
41
|
-
return
|
|
25
|
+
if (cachedProduct && !this.isProductCacheStale(cachedProduct)) {
|
|
26
|
+
const product = (0, libs_1.decompressJSON)(cachedProduct.productCompressed);
|
|
27
|
+
return product;
|
|
42
28
|
}
|
|
43
|
-
return
|
|
29
|
+
return undefined;
|
|
44
30
|
}
|
|
45
31
|
catch (error) {
|
|
46
32
|
helpers_1.Logger.error('Failed getShopifyProductCacheREST', { keyName: this.KEY_NAME, pixelId, productId, error });
|
|
47
|
-
return
|
|
33
|
+
return undefined;
|
|
48
34
|
}
|
|
49
35
|
};
|
|
50
|
-
|
|
51
|
-
const ttl =
|
|
52
|
-
const expiresAt = luxon_1.DateTime.utc().plus({
|
|
36
|
+
putProductInDynamoDBCache = async (pixelId, productId, product, ttlInSeconds) => {
|
|
37
|
+
const ttl = ttlInSeconds || this.dynamoDbCacheTtlInSeconds;
|
|
38
|
+
const expiresAt = luxon_1.DateTime.utc().plus({ seconds: ttl }).toSeconds();
|
|
39
|
+
const cachedAt = (0, libs_1.getCurrentTimestamp)();
|
|
40
|
+
const cachedAtEpoch = luxon_1.DateTime.utc().toSeconds();
|
|
41
|
+
const fullSha256 = crypto_1.default.createHash('sha256').update(JSON.stringify(product)).digest('hex');
|
|
42
|
+
const noInventoryProduct = { ...product, totalInventory: undefined, variants: product?.variants?.map(variant => ({ ...variant, inventoryQuantity: undefined, inventoryItem: undefined })) };
|
|
43
|
+
const noInventorySha256 = crypto_1.default.createHash('sha256').update(JSON.stringify(noInventoryProduct)).digest('hex');
|
|
44
|
+
const productCompressed = (0, libs_1.compressJSON)(product);
|
|
53
45
|
const shopifyProductCache = {
|
|
54
46
|
pixelId_productId: `${pixelId}_${productId}`,
|
|
55
47
|
pixelId,
|
|
56
48
|
productId,
|
|
57
|
-
productCompressed
|
|
58
|
-
|
|
49
|
+
productCompressed,
|
|
50
|
+
fullSha256,
|
|
51
|
+
noInventorySha256,
|
|
52
|
+
cachedAt,
|
|
53
|
+
cachedAtEpoch,
|
|
59
54
|
expiresAt
|
|
60
55
|
};
|
|
61
56
|
return await clients_1.DynamoDbClient.safePut(this.TABLE_NAME, shopifyProductCache);
|
|
62
57
|
};
|
|
58
|
+
isProductCacheStale = (cachedData) => {
|
|
59
|
+
if (cachedData?.expiresAt && cachedData.expiresAt < luxon_1.DateTime.utc().toSeconds()) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
};
|
|
63
64
|
}
|
|
64
65
|
exports.ShopifyProductsCacheDbService = ShopifyProductsCacheDbService;
|
|
65
66
|
//# sourceMappingURL=shopify-products-cache-db-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shopify-products-cache-db-service.js","sourceRoot":"","sources":["../../../../src/services/db/shopify-products-cache-db-service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shopify-products-cache-db-service.js","sourceRoot":"","sources":["../../../../src/services/db/shopify-products-cache-db-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,12 @@ export interface GetShopifyProductResponse extends ClientResponse<GetProductQuer
|
|
|
6
6
|
}
|
|
7
7
|
export declare class ShopifyProductsServiceV2 {
|
|
8
8
|
private productCacheService;
|
|
9
|
-
|
|
9
|
+
private shopifyProductsCacheDbService;
|
|
10
|
+
private TABLE_NAME;
|
|
11
|
+
private TABLE_KEY;
|
|
12
|
+
private redisCacheTtlInSeconds;
|
|
13
|
+
private dynamoDbCacheTtlInSeconds;
|
|
14
|
+
constructor(cacheLambdaFunctionArn: string, tableName: string, tableKey: string, redisCacheTtlInSeconds: number, dynamoDbCacheTtlInSeconds: number);
|
|
10
15
|
getShopifyProduct: (pixelId: string, shop: string, accessToken: string, productId: string, useCache?: boolean, updateCache?: boolean) => Promise<GetShopifyProductResponse | null>;
|
|
11
16
|
private getShopifyProductFromAPI;
|
|
12
17
|
}
|
|
@@ -5,27 +5,45 @@ const helpers_1 = require("../../../helpers");
|
|
|
5
5
|
const product_cache_service_1 = require("../../cache/product-cache-service");
|
|
6
6
|
const shopify_graphql_transformer_1 = require("../shopify-graphql-transformer");
|
|
7
7
|
const shopify_graphql_client_1 = require("../../../clients/third-party/shopify/shopify-graphql-client");
|
|
8
|
+
const shopify_products_cache_db_service_1 = require("../../db/shopify-products-cache-db-service");
|
|
8
9
|
class ShopifyProductsServiceV2 {
|
|
9
10
|
productCacheService;
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
shopifyProductsCacheDbService;
|
|
12
|
+
TABLE_NAME;
|
|
13
|
+
TABLE_KEY;
|
|
14
|
+
redisCacheTtlInSeconds;
|
|
15
|
+
dynamoDbCacheTtlInSeconds;
|
|
16
|
+
constructor(cacheLambdaFunctionArn, tableName, tableKey, redisCacheTtlInSeconds, dynamoDbCacheTtlInSeconds) {
|
|
17
|
+
this.TABLE_NAME = tableName;
|
|
18
|
+
this.TABLE_KEY = tableKey;
|
|
19
|
+
this.redisCacheTtlInSeconds = redisCacheTtlInSeconds;
|
|
20
|
+
this.dynamoDbCacheTtlInSeconds = dynamoDbCacheTtlInSeconds;
|
|
21
|
+
this.productCacheService = new product_cache_service_1.ProductCacheService(cacheLambdaFunctionArn, this.redisCacheTtlInSeconds);
|
|
22
|
+
this.shopifyProductsCacheDbService = new shopify_products_cache_db_service_1.ShopifyProductsCacheDbService(this.TABLE_NAME, this.TABLE_KEY, this.dynamoDbCacheTtlInSeconds);
|
|
12
23
|
}
|
|
13
24
|
getShopifyProduct = async (pixelId, shop, accessToken, productId, useCache = true, updateCache = true) => {
|
|
14
25
|
try {
|
|
15
26
|
let getShopifyProductResponse = {};
|
|
16
27
|
if (useCache) {
|
|
17
|
-
|
|
28
|
+
let product = await this.productCacheService.getProductFromCache(pixelId, productId);
|
|
18
29
|
if (product) {
|
|
19
30
|
helpers_1.Logger.debug('getShopifyProduct: Product found in cache', { pixelId, shop, productId, product });
|
|
20
31
|
getShopifyProductResponse.transformedProduct = product;
|
|
21
32
|
return getShopifyProductResponse;
|
|
22
33
|
}
|
|
34
|
+
product = await this.shopifyProductsCacheDbService.getProductFromDynamoDBCache(pixelId, productId);
|
|
35
|
+
if (product) {
|
|
36
|
+
helpers_1.Logger.debug('getShopifyProduct: Product found in dynamoDB cache', { pixelId, shop, productId, product });
|
|
37
|
+
getShopifyProductResponse.transformedProduct = product;
|
|
38
|
+
return getShopifyProductResponse;
|
|
39
|
+
}
|
|
23
40
|
}
|
|
24
41
|
getShopifyProductResponse = await this.getShopifyProductFromAPI(pixelId, shop, accessToken, productId, true);
|
|
25
42
|
if (getShopifyProductResponse?.transformedProduct && updateCache) {
|
|
26
43
|
const product = getShopifyProductResponse.transformedProduct;
|
|
27
44
|
helpers_1.Logger.debug('getShopifyProduct: Product found in ShopifyAPI, putting in cache', { pixelId, productId, product });
|
|
28
45
|
await this.productCacheService.putProductInCache(pixelId, productId, product);
|
|
46
|
+
await this.shopifyProductsCacheDbService.putProductInDynamoDBCache(pixelId, productId, product);
|
|
29
47
|
}
|
|
30
48
|
helpers_1.Logger.debug('getShopifyProduct: Returning product', { pixelId, shop, productId, product: getShopifyProductResponse?.transformedProduct });
|
|
31
49
|
return getShopifyProductResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shopify-products-serviceV2.js","sourceRoot":"","sources":["../../../../../src/services/shopify/products/shopify-products-serviceV2.ts"],"names":[],"mappings":";;;AAAA,8CAA0C;AAG1C,6EAAwE;AACxE,gFAA2E;AAC3E,wGAAmG;
|
|
1
|
+
{"version":3,"file":"shopify-products-serviceV2.js","sourceRoot":"","sources":["../../../../../src/services/shopify/products/shopify-products-serviceV2.ts"],"names":[],"mappings":";;;AAAA,8CAA0C;AAG1C,6EAAwE;AACxE,gFAA2E;AAC3E,wGAAmG;AAGnG,kGAA2F;AAM3F,MAAa,wBAAwB;IAC3B,mBAAmB,CAAsB;IACzC,6BAA6B,CAAgC;IAC7D,UAAU,CAAS;IACnB,SAAS,CAAS;IAClB,sBAAsB,CAAS;IAC/B,yBAAyB,CAAS;IAE1C,YAAY,sBAA8B,EAAE,SAAiB,EAAE,QAAgB,EAAE,sBAA8B,EAAE,yBAAiC;QAChJ,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAC;QACrD,IAAI,CAAC,yBAAyB,GAAG,yBAAyB,CAAC;QAE3D,IAAI,CAAC,mBAAmB,GAAG,IAAI,2CAAmB,CAAC,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACxG,IAAI,CAAC,6BAA6B,GAAG,IAAI,iEAA6B,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC1I,CAAC;IAEM,iBAAiB,GAAG,KAAK,EAAE,OAAe,EAAE,IAAY,EAAE,WAAmB,EAAE,SAAiB,EAAE,QAAQ,GAAG,IAAI,EAAE,WAAW,GAAG,IAAI,EAA6C,EAAE;QACzL,IAAI;YACF,IAAI,yBAAyB,GAAqC,EAAE,CAAC;YACrE,IAAI,QAAQ,EAAE;gBACZ,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;gBACrF,IAAI,OAAO,EAAE;oBACX,gBAAM,CAAC,KAAK,CAAC,2CAA2C,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;oBACjG,yBAAyB,CAAC,kBAAkB,GAAG,OAAO,CAAC;oBACvD,OAAO,yBAAyB,CAAC;iBAClC;gBAED,OAAO,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAAC,2BAA2B,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;gBACnG,IAAI,OAAO,EAAE;oBACX,gBAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;oBAC1G,yBAAyB,CAAC,kBAAkB,GAAG,OAAO,CAAC;oBACvD,OAAO,yBAAyB,CAAC;iBAClC;aACF;YACD,yBAAyB,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;YAC7G,IAAI,yBAAyB,EAAE,kBAAkB,IAAI,WAAW,EAAE;gBAChE,MAAM,OAAO,GAAG,yBAAyB,CAAC,kBAAkB,CAAC;gBAC7D,gBAAM,CAAC,KAAK,CAAC,kEAAkE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;gBAClH,MAAM,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;gBAC9E,MAAM,IAAI,CAAC,6BAA6B,CAAC,yBAAyB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;aACjG;YACD,gBAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3I,OAAO,yBAAyB,CAAC;SAClC;QAAC,OAAO,KAAK,EAAE;YACd,gBAAM,CAAC,KAAK,CAAC,+DAA+D,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACzF,OAAO,IAAI,CAAC;SACb;IACH,CAAC,CAAC;IAEM,wBAAwB,GAAG,KAAK,EAAE,OAAe,EAAE,IAAY,EAAE,WAAmB,EAAE,SAAiB,EAAE,cAAc,GAAG,IAAI,EAA6C,EAAE;QACnL,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,6CAAoB,CAAC,6BAA6B,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7G,MAAM,yBAAyB,GAA8B,QAAQ,CAAC;YACtE,IAAI,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE;gBAC3B,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAkB,CAAC;gBACjD,gBAAM,CAAC,KAAK,CAAC,uDAAuD,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC7G,IAAI,cAAc,EAAE;oBAClB,MAAM,kBAAkB,GAAG,uDAAyB,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;oBACzF,yBAAyB,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;oBAClE,gBAAM,CAAC,KAAK,CAAC,+CAA+C,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,kBAAkB,EAAE,yBAAyB,CAAC,kBAAkB,EAAE,CAAC,CAAC;iBAC/J;gBACD,OAAO,yBAAyB,CAAC;aAClC;iBAAM;gBACL,gBAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC1H,OAAO,yBAAyB,CAAC;aAClC;SACF;QAAC,OAAO,KAAK,EAAE;YACd,gBAAM,CAAC,KAAK,CAAC,2DAA2D,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;YACtJ,OAAO,IAAI,CAAC;SACb;IACH,CAAC,CAAA;CACF;AAzED,4DAyEC"}
|
|
@@ -10,7 +10,8 @@ export interface ProductCache extends GenericCachedObject {
|
|
|
10
10
|
export declare const getProductCacheKey: (pixelId: string, productId: string) => string;
|
|
11
11
|
export declare class ProductCacheService {
|
|
12
12
|
private genericCacheService;
|
|
13
|
-
|
|
13
|
+
private redisCacheTtlInSeconds;
|
|
14
|
+
constructor(cacheLambdaFunctionArn: string, redisCacheTtlInSeconds: number);
|
|
14
15
|
getCacheKey: (pixelId: string, productId: string) => string;
|
|
15
16
|
getProductFromCache: (pixelId: string, productId: string) => Promise<InternalProduct | undefined>;
|
|
16
17
|
getProductCache: (pixelId: string, productId: string) => Promise<ProductCache | undefined>;
|
|
@@ -8,8 +8,10 @@ export const getProductCacheKey = (pixelId, productId) => {
|
|
|
8
8
|
};
|
|
9
9
|
export class ProductCacheService {
|
|
10
10
|
genericCacheService;
|
|
11
|
-
|
|
11
|
+
redisCacheTtlInSeconds;
|
|
12
|
+
constructor(cacheLambdaFunctionArn, redisCacheTtlInSeconds) {
|
|
12
13
|
this.genericCacheService = new GenericCacheService(cacheLambdaFunctionArn);
|
|
14
|
+
this.redisCacheTtlInSeconds = redisCacheTtlInSeconds || DEFAULT_TTL_IN_SECONDS;
|
|
13
15
|
}
|
|
14
16
|
getCacheKey = (pixelId, productId) => {
|
|
15
17
|
return getProductCacheKey(pixelId, productId);
|
|
@@ -29,7 +31,7 @@ export class ProductCacheService {
|
|
|
29
31
|
};
|
|
30
32
|
putProductInCache = async (pixelId, productId, product, ttlInSeconds) => {
|
|
31
33
|
const cacheKey = this.getCacheKey(pixelId, productId);
|
|
32
|
-
const ttl = ttlInSeconds ||
|
|
34
|
+
const ttl = ttlInSeconds || this.redisCacheTtlInSeconds;
|
|
33
35
|
const expiresAt = DateTime.utc().plus({ seconds: ttl }).toSeconds();
|
|
34
36
|
const cachedAtEpoch = DateTime.utc().toSeconds();
|
|
35
37
|
const fullSha256 = crypto.createHash('sha256').update(JSON.stringify(product)).digest('hex');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-cache-service.js","sourceRoot":"","sources":["../../../../src/services/cache/product-cache-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAU7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAE,SAAiB,EAAE,EAAE;IACvE,OAAO,oBAAoB,OAAO,IAAI,SAAS,EAAE,CAAC;AACpD,CAAC,CAAA;AAED,MAAM,OAAO,mBAAmB;IACtB,mBAAmB,CAAsB;
|
|
1
|
+
{"version":3,"file":"product-cache-service.js","sourceRoot":"","sources":["../../../../src/services/cache/product-cache-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { InternalProduct } from '../shopify/types/product';
|
|
2
|
+
import { ProductCache } from '../cache';
|
|
3
|
+
export interface ShopifyProductDynamoDbCache extends ProductCache {
|
|
4
|
+
pixelId_productId: string;
|
|
5
|
+
pixelId: string;
|
|
6
|
+
productId: string;
|
|
7
|
+
}
|
|
2
8
|
export declare class ShopifyProductsCacheDbService {
|
|
3
9
|
TABLE_NAME: string;
|
|
4
10
|
KEY_NAME: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
private dynamoDbCacheTtlInSeconds;
|
|
12
|
+
constructor(tableName: string, keyName: string, dynamoDbCacheTtlInSeconds: number);
|
|
13
|
+
getProductFromDynamoDBCache: (pixelId: string, productId: string) => Promise<InternalProduct | undefined>;
|
|
14
|
+
putProductInDynamoDBCache: (pixelId: string, productId: string, product: InternalProduct, ttlInSeconds?: number) => Promise<import("@aws-sdk/lib-dynamodb").PutCommandOutput | null>;
|
|
15
|
+
private isProductCacheStale;
|
|
9
16
|
}
|
|
@@ -1,61 +1,59 @@
|
|
|
1
|
-
import { DynamoDbClient
|
|
1
|
+
import { DynamoDbClient } from '../../clients';
|
|
2
2
|
import { compressJSON, decompressJSON, getCurrentTimestamp } from '../../libs';
|
|
3
3
|
import { DateTime } from 'luxon';
|
|
4
4
|
import { Logger } from '../../helpers';
|
|
5
|
+
import crypto from 'crypto';
|
|
6
|
+
const DEFAULT_TTL_IN_SECONDS = 7 * 24 * 3600;
|
|
5
7
|
export class ShopifyProductsCacheDbService {
|
|
6
8
|
TABLE_NAME;
|
|
7
9
|
KEY_NAME;
|
|
8
|
-
|
|
10
|
+
dynamoDbCacheTtlInSeconds;
|
|
11
|
+
constructor(tableName, keyName, dynamoDbCacheTtlInSeconds) {
|
|
9
12
|
this.TABLE_NAME = tableName;
|
|
10
13
|
this.KEY_NAME = keyName;
|
|
14
|
+
this.dynamoDbCacheTtlInSeconds = dynamoDbCacheTtlInSeconds || DEFAULT_TTL_IN_SECONDS;
|
|
11
15
|
}
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const cachedShopifyProduct = await this.getShopifyProductFromCacheREST(pixelId, productId);
|
|
15
|
-
if (cachedShopifyProduct) {
|
|
16
|
-
return cachedShopifyProduct.product;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
const productRes = await ShopifyClient.getProductREST(shop, accessToken, productId);
|
|
20
|
-
if (productRes.status === 200 && productRes?.data?.product) {
|
|
21
|
-
const product = productRes.data.product;
|
|
22
|
-
await this.putShopifyProductCacheREST(pixelId, productId, product);
|
|
23
|
-
return product;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
Logger.error('Failed lookupShopifyProductCacheREST', { error });
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
getShopifyProductFromCacheREST = async (pixelId, productId) => {
|
|
16
|
+
getProductFromDynamoDBCache = async (pixelId, productId) => {
|
|
34
17
|
try {
|
|
35
18
|
const cachedProduct = await DynamoDbClient.safeGet(this.TABLE_NAME, this.KEY_NAME, `${pixelId}_${productId}`);
|
|
36
|
-
if (cachedProduct) {
|
|
37
|
-
|
|
38
|
-
return
|
|
19
|
+
if (cachedProduct && !this.isProductCacheStale(cachedProduct)) {
|
|
20
|
+
const product = decompressJSON(cachedProduct.productCompressed);
|
|
21
|
+
return product;
|
|
39
22
|
}
|
|
40
|
-
return
|
|
23
|
+
return undefined;
|
|
41
24
|
}
|
|
42
25
|
catch (error) {
|
|
43
26
|
Logger.error('Failed getShopifyProductCacheREST', { keyName: this.KEY_NAME, pixelId, productId, error });
|
|
44
|
-
return
|
|
27
|
+
return undefined;
|
|
45
28
|
}
|
|
46
29
|
};
|
|
47
|
-
|
|
48
|
-
const ttl =
|
|
49
|
-
const expiresAt = DateTime.utc().plus({
|
|
30
|
+
putProductInDynamoDBCache = async (pixelId, productId, product, ttlInSeconds) => {
|
|
31
|
+
const ttl = ttlInSeconds || this.dynamoDbCacheTtlInSeconds;
|
|
32
|
+
const expiresAt = DateTime.utc().plus({ seconds: ttl }).toSeconds();
|
|
33
|
+
const cachedAt = getCurrentTimestamp();
|
|
34
|
+
const cachedAtEpoch = DateTime.utc().toSeconds();
|
|
35
|
+
const fullSha256 = crypto.createHash('sha256').update(JSON.stringify(product)).digest('hex');
|
|
36
|
+
const noInventoryProduct = { ...product, totalInventory: undefined, variants: product?.variants?.map(variant => ({ ...variant, inventoryQuantity: undefined, inventoryItem: undefined })) };
|
|
37
|
+
const noInventorySha256 = crypto.createHash('sha256').update(JSON.stringify(noInventoryProduct)).digest('hex');
|
|
38
|
+
const productCompressed = compressJSON(product);
|
|
50
39
|
const shopifyProductCache = {
|
|
51
40
|
pixelId_productId: `${pixelId}_${productId}`,
|
|
52
41
|
pixelId,
|
|
53
42
|
productId,
|
|
54
|
-
productCompressed
|
|
55
|
-
|
|
43
|
+
productCompressed,
|
|
44
|
+
fullSha256,
|
|
45
|
+
noInventorySha256,
|
|
46
|
+
cachedAt,
|
|
47
|
+
cachedAtEpoch,
|
|
56
48
|
expiresAt
|
|
57
49
|
};
|
|
58
50
|
return await DynamoDbClient.safePut(this.TABLE_NAME, shopifyProductCache);
|
|
59
51
|
};
|
|
52
|
+
isProductCacheStale = (cachedData) => {
|
|
53
|
+
if (cachedData?.expiresAt && cachedData.expiresAt < DateTime.utc().toSeconds()) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
60
58
|
}
|
|
61
59
|
//# sourceMappingURL=shopify-products-cache-db-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shopify-products-cache-db-service.js","sourceRoot":"","sources":["../../../../src/services/db/shopify-products-cache-db-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"shopify-products-cache-db-service.js","sourceRoot":"","sources":["../../../../src/services/db/shopify-products-cache-db-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,12 @@ export interface GetShopifyProductResponse extends ClientResponse<GetProductQuer
|
|
|
6
6
|
}
|
|
7
7
|
export declare class ShopifyProductsServiceV2 {
|
|
8
8
|
private productCacheService;
|
|
9
|
-
|
|
9
|
+
private shopifyProductsCacheDbService;
|
|
10
|
+
private TABLE_NAME;
|
|
11
|
+
private TABLE_KEY;
|
|
12
|
+
private redisCacheTtlInSeconds;
|
|
13
|
+
private dynamoDbCacheTtlInSeconds;
|
|
14
|
+
constructor(cacheLambdaFunctionArn: string, tableName: string, tableKey: string, redisCacheTtlInSeconds: number, dynamoDbCacheTtlInSeconds: number);
|
|
10
15
|
getShopifyProduct: (pixelId: string, shop: string, accessToken: string, productId: string, useCache?: boolean, updateCache?: boolean) => Promise<GetShopifyProductResponse | null>;
|
|
11
16
|
private getShopifyProductFromAPI;
|
|
12
17
|
}
|
|
@@ -2,27 +2,45 @@ import { Logger } from '../../../helpers';
|
|
|
2
2
|
import { ProductCacheService } from '../../cache/product-cache-service';
|
|
3
3
|
import { ShopifyGraphQLTransformer } from '../shopify-graphql-transformer';
|
|
4
4
|
import { ShopifyGraphQLClient } from '../../../clients/third-party/shopify/shopify-graphql-client';
|
|
5
|
+
import { ShopifyProductsCacheDbService } from '../../db/shopify-products-cache-db-service';
|
|
5
6
|
export class ShopifyProductsServiceV2 {
|
|
6
7
|
productCacheService;
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
shopifyProductsCacheDbService;
|
|
9
|
+
TABLE_NAME;
|
|
10
|
+
TABLE_KEY;
|
|
11
|
+
redisCacheTtlInSeconds;
|
|
12
|
+
dynamoDbCacheTtlInSeconds;
|
|
13
|
+
constructor(cacheLambdaFunctionArn, tableName, tableKey, redisCacheTtlInSeconds, dynamoDbCacheTtlInSeconds) {
|
|
14
|
+
this.TABLE_NAME = tableName;
|
|
15
|
+
this.TABLE_KEY = tableKey;
|
|
16
|
+
this.redisCacheTtlInSeconds = redisCacheTtlInSeconds;
|
|
17
|
+
this.dynamoDbCacheTtlInSeconds = dynamoDbCacheTtlInSeconds;
|
|
18
|
+
this.productCacheService = new ProductCacheService(cacheLambdaFunctionArn, this.redisCacheTtlInSeconds);
|
|
19
|
+
this.shopifyProductsCacheDbService = new ShopifyProductsCacheDbService(this.TABLE_NAME, this.TABLE_KEY, this.dynamoDbCacheTtlInSeconds);
|
|
9
20
|
}
|
|
10
21
|
getShopifyProduct = async (pixelId, shop, accessToken, productId, useCache = true, updateCache = true) => {
|
|
11
22
|
try {
|
|
12
23
|
let getShopifyProductResponse = {};
|
|
13
24
|
if (useCache) {
|
|
14
|
-
|
|
25
|
+
let product = await this.productCacheService.getProductFromCache(pixelId, productId);
|
|
15
26
|
if (product) {
|
|
16
27
|
Logger.debug('getShopifyProduct: Product found in cache', { pixelId, shop, productId, product });
|
|
17
28
|
getShopifyProductResponse.transformedProduct = product;
|
|
18
29
|
return getShopifyProductResponse;
|
|
19
30
|
}
|
|
31
|
+
product = await this.shopifyProductsCacheDbService.getProductFromDynamoDBCache(pixelId, productId);
|
|
32
|
+
if (product) {
|
|
33
|
+
Logger.debug('getShopifyProduct: Product found in dynamoDB cache', { pixelId, shop, productId, product });
|
|
34
|
+
getShopifyProductResponse.transformedProduct = product;
|
|
35
|
+
return getShopifyProductResponse;
|
|
36
|
+
}
|
|
20
37
|
}
|
|
21
38
|
getShopifyProductResponse = await this.getShopifyProductFromAPI(pixelId, shop, accessToken, productId, true);
|
|
22
39
|
if (getShopifyProductResponse?.transformedProduct && updateCache) {
|
|
23
40
|
const product = getShopifyProductResponse.transformedProduct;
|
|
24
41
|
Logger.debug('getShopifyProduct: Product found in ShopifyAPI, putting in cache', { pixelId, productId, product });
|
|
25
42
|
await this.productCacheService.putProductInCache(pixelId, productId, product);
|
|
43
|
+
await this.shopifyProductsCacheDbService.putProductInDynamoDBCache(pixelId, productId, product);
|
|
26
44
|
}
|
|
27
45
|
Logger.debug('getShopifyProduct: Returning product', { pixelId, shop, productId, product: getShopifyProductResponse?.transformedProduct });
|
|
28
46
|
return getShopifyProductResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shopify-products-serviceV2.js","sourceRoot":"","sources":["../../../../../src/services/shopify/products/shopify-products-serviceV2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6DAA6D,CAAC;
|
|
1
|
+
{"version":3,"file":"shopify-products-serviceV2.js","sourceRoot":"","sources":["../../../../../src/services/shopify/products/shopify-products-serviceV2.ts"],"names":[],"mappings":"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"}
|