commerce/framework/agility/next.file.sync.js
2021-01-18 12:39:16 -05:00

153 lines
3.4 KiB
JavaScript

const fs = require('fs')
const os = require('os')
const path = require('path')
const { lockSync, unlockSync, checkSync, check } = require("proper-lockfile")
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
}
const getFilePath = ({ options, itemType, languageCode, itemID }) => {
const fileName = `${itemID}.json`;
return path.join(options.rootPath, languageCode, itemType, fileName);
}
const saveItem = async ({ options, item, itemType, languageCode, itemID }) => {
let filePath = getFilePath({ options, itemType, languageCode, itemID });
let dirPath = path.dirname(filePath);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
let json = JSON.stringify(item);
fs.writeFileSync(filePath, json);
}
const deleteItem = async ({ options, itemType, languageCode, itemID }) => {
let filePath = getFilePath({ options, itemType, languageCode, itemID });
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
}
const mergeItemToList = async ({ options, item, languageCode, itemID, referenceName, definitionName }) => {
let contentList = await getItem({ options, itemType: "list", languageCode, itemID: referenceName });
if (contentList == null) {
//initialize the list
contentList = [item];
} else {
//replace the item...
const cIndex = contentList.findIndex((ci) => {
return ci.contentID === itemID;
});
if (item.properties.state === 3) {
//*** deleted item (remove from the list) ***
if (cIndex >= 0) {
//remove the item
contentList.splice(cIndex, 1);
}
} else {
//*** regular item (merge) ***
if (cIndex >= 0) {
//replace the existing item
contentList[cIndex] = item;
} else {
//and it to the end of the
contentList.push(item);
}
}
}
await saveItem({ options, item: contentList, itemType: "list", languageCode, itemID: referenceName });
}
const getItem = async ({ options, itemType, languageCode, itemID }) => {
let filePath = getFilePath({ options, itemType, languageCode, itemID });
if (!fs.existsSync(filePath)) return null;
let json = fs.readFileSync(filePath, 'utf8');
return JSON.parse(json);
}
const clearItems = async ({ options }) => {
fs.rmdirSync(options.rootPath, { recursive: true })
}
const waitOnLock = async (lockFile) => {
while (await check(lockFile)) {
await sleep(100)
}
}
const mutexLock = async () => {
const dir = os.tmpdir();
const lockFile = `${dir}/${"agility-sync"}.mutex`
if (! fs.existsSync(lockFile)) {
fs.writeFileSync(lockFile, "agility-sync");
}
//THE LOCK IS ALREADY HELD - WAIT UP!
await waitOnLock(lockFile)
try {
return lockSync(lockFile)
} catch (err) {
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
await sleep(100)
await waitOnLock(lockFile)
try {
return lockSync(lockFile)
} catch (e2) {
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
await sleep(100)
await waitOnLock(lockFile)
return lockSync(lockFile)
}
}
}
throw Error("The mutex lock could not be obtained.")
}
}
module.exports = {
saveItem,
deleteItem,
mergeItemToList,
getItem,
clearItems,
mutexLock
}