Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable:adjacent-overload-signatures
const perf_hooks_1 = require("perf_hooks");
const fs_1 = require("fs");
const path_1 = require("path");
const exotic_1 = require("exotic");
const graphql_toolset_1 = require("@skava/graphql-toolset");
const log_1 = require("../../log");
const bindings_1 = require("../catalog/bindings");
const bindings_2 = require("../categories/bindings");
const index_1 = require("../index");
const cache_1 = require("../../cache");
const cache = new Map();
cache.set('categories', []);
cache.set('productList', new Map());
cache.set('productDetail', new Map());
cache.set('catalogLite', new Map());
const scoped = {
    requestCache: undefined,
    appBindings: undefined,
};
function create() {
    scoped.requestCache = cache_1.toCache();
    // @todo fix typings in @skava/graphql-toolset
    scoped.appBindings = graphql_toolset_1.toGraphqlModuleTest({
        graphqlModule: index_1.AppModules,
        options: {
            cache: scoped.requestCache,
        },
    });
}
async function mapCategories(categories = exotic_1.EMPTY_ARRAY) {
    console.log('___mapCategories___', categories);
    const catalogBindings = await bindings_1.toCatalogHelpers(scoped.appBindings);
    /**
     * @todo return and flatmap all promises to send all at once...
     */
    const allThesePromises = categories.map((category = { identifier: '@@EMPTY_CATEGORY' }) => new Promise(async (done) => {
        /**
         * @todo put catalogFull + catalogLite => same array as pages
         */
        console.log(`getting category ${category.name}`);
        if (cache.get('productList').has(category.identifier)) {
            console.log(`[sponge]{productList} already had ${category.identifier}`);
            done();
            return;
        }
        const catalogResponse = await catalogBindings.getProductList({
            categoryId: category.identifier,
            limit: 50,
        });
        const { productList } = catalogResponse.data;
        cache.get('productList').set(productList.identifier, productList);
        // @todo validate
        const products = productList.products || [];
        /**
         * @todo remove errors with `Sorry , no results found! Please check the spelling or try searching for something else`
         * @todo split into fn
         */
        const pagination = Object.assign({}, productList.pagination, { limit: 50 });
        console.log('___PAGINATION___', { offset: pagination.offset, totalPages: pagination.totalPages }, +pagination.totalPages > +pagination.offset);
        const pages = [];
        /**
         * @todo I think this is not working when we *get* from the cache
         *       it does not include `page=`
         */
        while (+pagination.totalPages > +pagination.offset) {
            console.log(`getting next page for ${productList.identifier} ${pagination.offset} totalPages: ${pagination.totalPages}`);
            pagination.offset += 1;
            const offset = pagination.offset;
            pages.push(new Promise(async (donePage) => {
                try {
                    const productListPaginatedKey = productList.identifier + `offset=${offset}`;
                    if (cache.get('productList').has(productListPaginatedKey)) {
                        console.log(`[sponge]{plp} already had ${productListPaginatedKey}`);
                        donePage();
                        return;
                    }
                    const nextCatalogResponse = await catalogBindings.getProductList({
                        categoryId: category.identifier,
                        offset,
                        limit: pagination.limit,
                    });
                    const nextProductList = nextCatalogResponse.data.productList;
                    pagination.hasNextPage = nextProductList.pagination.hasNextPage;
                    products.push(...nextProductList.products);
                    cache
                        .get('productList')
                        .set(productListPaginatedKey, nextProductList);
                    donePage();
                }
                catch (exception) {
                    console.error(exception);
                }
            }));
        }
        // all pages, at ~ same time
        await Promise.all(pages);
        // @todo, final step would be to query all selected facets o.o
        const catalogLiteResponse = await catalogBindings.getCatalogLite({
            categoryId: category.identifier,
        });
        const { catalogLite } = catalogLiteResponse.data;
        cache.get('catalogLite').set(category.identifier, catalogLite);
        const andTheyAllFeelSoWastedOnMyself = products.map(async (productListProduct) => {
            if (cache.get('productDetail').has(productListProduct.identifier)) {
                console.log(`[sponge]{product} already had ${productListProduct.identifier}`);
                return Promise.resolve();
            }
            const productDetailResponse = await catalogBindings.getProductDetail({
                productId: productListProduct.identifier,
            });
            const product = productDetailResponse.data.productDetail;
            cache.get('productDetail').set(product.identifier, product);
            return Promise.resolve();
        });
        console.log('waiting for products');
        await Promise.all(andTheyAllFeelSoWastedOnMyself);
        console.log('done waiting for products');
        if (exotic_1.isNonEmptyArray(category.categories)) {
            await mapCategories(category.categories);
            done();
        }
        else {
            done();
            return Promise.resolve();
        }
    }));
    // @todo return?
    await Promise.all(allThesePromises);
}
async function getCategories() {
    const categoriesBinding = await bindings_2.toCategoriesHelpers(scoped.appBindings);
    const response = await categoriesBinding.getCategories();
    const categories = response.data.categories;
    cache.set('categories', categories);
    return categories;
}
function fromCacheToSerialized(cacheArg) {
    return {
        categories: cacheArg.get('categories'),
        productList: exotic_1.fromMapToObj(cacheArg.get('productList')),
        productDetail: exotic_1.fromMapToObj(cacheArg.get('productDetail')),
        catalogLite: exotic_1.fromMapToObj(cacheArg.get('catalogLite')),
    };
}
class Timer {
    constructor() {
        this.store = new Map();
    }
    start() {
        const now = perf_hooks_1.performance.now();
        this.store.set('start', now);
        return this;
    }
    end() {
        const now = perf_hooks_1.performance.now();
        this.store.set('end', now);
        return this;
    }
    log() {
        const start = this.store.get('start');
        const end = this.store.get('end');
        const duration = end - start;
        log_1.logger.info('[sponge] time: ' + duration);
        return this;
    }
}
function logCache() {
    const cacheAsObj = fromCacheToSerialized(cache);
    console.log('\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n');
    console.log(cacheAsObj);
}
const redis_1 = require("../../cache/redis");
async function writeToRedis() {
    const cacheAsObj = fromCacheToSerialized(cache);
    await Promise.all([
        ...Object.keys(cacheAsObj).map(key => redis_1.set(key, cacheAsObj[key])),
        ...Object.keys(cacheAsObj.productList).map(key => redis_1.set('productList.' + key, cacheAsObj.productList[key])),
        ...Object.keys(cacheAsObj.catalogLite).map(key => redis_1.set('catalogLite.' + key, cacheAsObj.catalogLite[key])),
        ...Object.keys(cacheAsObj.productDetail).map(key => redis_1.set('productDetail.' + key, cacheAsObj.productDetail[key])),
    ]);
}
async function persist() {
    if (process.env.CACHE_TYPE === 'redis') {
        await writeToRedis();
    }
    else {
        fs_1.writeFileSync(path_1.resolve(__dirname, './sponge.json'), JSON.stringify(cacheAsObj, undefined, 2));
    }
}
async function soakSponge() {
    create();
    await scoped.requestCache.rehydrate();
    const timer = new Timer().start();
    const categories = await getCategories();
    await mapCategories(categories);
    timer.end().log();
    persist();
}
exports.soakSponge = soakSponge;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ncmFwaHFsLW1vZHVsZXMvc3BvbmdlL2RlcHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw4Q0FBOEM7QUFDOUMsMkNBQXdDO0FBQ3hDLDJCQUFrQztBQUNsQywrQkFBOEI7QUFDOUIsbUNBQW1FO0FBQ25FLDREQUE2RTtBQUM3RSxtQ0FBa0M7QUFDbEMsa0RBQXNEO0FBTXRELHFEQUE0RDtBQU01RCxvQ0FBcUM7QUFDckMsdUNBQXFDO0FBbUJyQyxNQUFNLEtBQUssR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQTtBQUNwQyxLQUFLLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQTtBQUMzQixLQUFLLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUE7QUFDbkMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBQ3JDLEtBQUssQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQTtBQUVuQyxNQUFNLE1BQU0sR0FHUjtJQUNGLFlBQVksRUFBRSxTQUFTO0lBQ3ZCLFdBQVcsRUFBRSxTQUFTO0NBQ3ZCLENBQUE7QUFDRCxTQUFTLE1BQU07SUFDYixNQUFNLENBQUMsWUFBWSxHQUFHLGVBQU8sRUFBRSxDQUFBO0lBQy9CLDhDQUE4QztJQUM5QyxNQUFNLENBQUMsV0FBVyxHQUFHLHFDQUFtQixDQUFDO1FBQ3ZDLGFBQWEsRUFBRSxrQkFBVTtRQUN6QixPQUFPLEVBQUU7WUFDUCxLQUFLLEVBQUUsTUFBTSxDQUFDLFlBQVk7U0FDM0I7S0FDRixDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGFBQWEsQ0FDMUIsYUFBK0Isb0JBQWtCO0lBRWpELE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLEVB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