function cloneCache()

in modules/backend/migrations/1516948939797-migrate-configs.js [50:127]


function cloneCache(clustersModel, cachesModel, domainsModel, cache) {
    const cacheId = cache._id;
    const clusters = cache.clusters;

    cache.clusters = [];

    if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind === null)
        delete cache.cacheStoreFactory.kind;

    return _.reduce(clusters, (start, cluster, idx) => start.then(() => {
        if (idx > 0) {
            delete cache._id;

            const newCache = _.clone(cache);
            const domainIds = newCache.domains;

            newCache.clusters = [cluster];
            newCache.domains = [];

            return clustersModel.updateMany({_id: {$in: newCache.clusters}}, {$pull: {caches: cacheId}}).exec()
                .then(() => cachesModel.create(newCache))
                .catch((err) => {
                    if (err.code === DUPLICATE_KEY_ERROR) {
                        const retryWith = makeDup(newCache.name);

                        error(`Failed to clone cache, will change cache name and retry [cache=${newCache.name}, retryWith=${retryWith}]`);

                        newCache.name = retryWith;

                        return cachesModel.create(newCache);
                    }

                    return Promise.reject(err);
                })
                .then((clone) => clustersModel.updateMany({_id: {$in: newCache.clusters}}, {$addToSet: {caches: clone._id}}).exec()
                    .then(() => clone))
                .then((clone) => {
                    if (_.isEmpty(domainIds))
                        return Promise.resolve();

                    return _.reduce(domainIds, (start, domainId) => start.then(() => {
                        return domainsModel.findOne({_id: domainId}).lean().exec()
                            .then((domain) => {
                                delete domain._id;

                                const newDomain = _.clone(domain);

                                newDomain.caches = [clone._id];
                                newDomain.clusters = [cluster];

                                return domainsModel.create(newDomain)
                                    .catch((err) => {
                                        if (err.code === DUPLICATE_KEY_ERROR) {
                                            const retryWith = makeDup(newDomain.valueType);

                                            error(`Failed to clone domain, will change type name and retry [cache=${newCache.name}, valueType=${newDomain.valueType}, retryWith=${retryWith}]`);

                                            newDomain.valueType = retryWith;

                                            return domainsModel.create(newDomain);
                                        }
                                    })
                                    .then((createdDomain) => {
                                        return clustersModel.updateOne({_id: cluster}, {$addToSet: {models: createdDomain._id}}).exec()
                                            .then(() => cachesModel.updateOne({_id: clone.id}, {$addToSet: {domains: createdDomain._id}}));
                                    })
                                    .catch((err) => error('Failed to clone domain during cache clone', err));
                            })
                            .catch((err) => error(`Failed to duplicate domain model[domain=${domainId}], cache=${clone.name}]`, err));
                    }), Promise.resolve());
                })
                .catch((err) => error(`Failed to clone cache[id=${cacheId}, name=${cache.name}]`, err));
        }

        return cachesModel.updateOne({_id: cacheId}, {clusters: [cluster]}).exec()
            .then(() => clustersModel.updateOne({_id: cluster}, {$addToSet: {models: {$each: cache.domains}}}).exec());
    }), Promise.resolve());
}