Skip to content

Commit

Permalink
feat: get config using CoCreate-config
Browse files Browse the repository at this point in the history
  • Loading branch information
frankpagan committed Nov 25, 2023
1 parent 80e25d6 commit 8e0b9fc
Showing 1 changed file with 93 additions and 119 deletions.
212 changes: 93 additions & 119 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,97 @@ const eventEmitter = new EventEmitter();
const fs = require('fs').promises;
const path = require('path');
const vm = require('vm');

const scriptsDirectory = './scripts';
const Config = require("@cocreate/config");

class CoCreateLazyLoader {
constructor(crud) {
this.wsManager = crud.wsManager
this.crud = crud
this.exclusion = { ...require.cache };
this.modules = {};
this.init()
}

init() {
// TODO: check CoCreate.config.js using config
const lazyLoadConfig = Config('lazyload')
if (!lazyLoadConfig)
async init() {
// Function to create the scripts directory if it doesn't exist
async function createScriptsDirectory() {
try {
const scriptsDirectory = './scripts';
await fs.mkdir(scriptsDirectory, { recursive: true });
console.log(`Scripts directory created at ${scriptsDirectory}`);
} catch (error) {
console.error('Error creating scripts directory:', error);
throw error; // Halt execution if directory creation fails
}
}

// Call this function at the start of your application
createScriptsDirectory();

const config = await Config('lazyload', false, false)
if (!config)
return

for (let key of Object.keys(lazyLoadConfig.lazyload)) {
let moduleConfig = lazyLoadConfig.lazyload[key];
for (let key of Object.keys(config.lazyload)) {
let moduleConfig = config.lazyload[key];
eventEmitter.on(moduleConfig.event, async () => {
try {
const module = await require(moduleConfig.path);
this.executeScriptWithTimeout(key, moduleConfig)
});
}

if (typeof moduleConfig.unload === 'number') {
setTimeout(() => {
// Implement module unload logic
}, moduleConfig.unload);
}
// eventEmitter.emit('openai');

// Use openaiModule here
}

} catch (error) {
console.log()
async executeScriptWithTimeout(moduleName, moduleConfig) {
try {
if (!moduleConfig.content) {
if (moduleConfig.path)
moduleConfig.content = await require(moduleConfig.path)
else {
try {
const scriptPath = path.join(scriptsDirectory, `${moduleName}.js`);
await fs.access(scriptPath);
moduleConfig.content = await fs.readFile(scriptPath, 'utf8');
} catch {
moduleConfig.content = await fetchScriptFromDatabaseAndSave(moduleName, moduleConfig);
}
}
});

console.log("Module Key:", key);
console.log("Module Config:", moduleConfig);
}

}
if (moduleConfig.unload === false || moduleConfig.unload === 'false')
return
else if (moduleConfig.unload === true || moduleConfig.unload === 'true')
console.log('config should unload after completeion ')
else if (moduleConfig.unload = parseInt(moduleConfig.unload, 10)) {
// Check if the script is already loaded
if (moduleConfig.timeout) {
clearTimeout(moduleConfig.timeout);
} else if (!moduleConfig.path) {
// Execute the script
moduleConfig.context = new vm.createContext({});
const script = new vm.Script(moduleConfig.context);
script.runInContext(context);
}

}
}
// Reset or set the timeout
const timeout = setTimeout(() => {
delete this.modules[moduleName]
delete moduleConfig.timeout
delete moduleConfig.context
delete moduleConfig.content
console.log(`Module ${moduleName} removed due to inactivity.`);
clearModuleCache(moduleName);

// Emitting the event somewhere in your application
// eventEmitter.emit('openai');
}, moduleConfig.unload);

let exclusion = {};
moduleConfig.timeout = timeout
}
} catch (error) {
console.log(error)
}
}

function generateExclusionList() {
exclusion = { ...require.cache };
}

function getModuleDependencies(modulePath) {
Expand All @@ -68,7 +109,13 @@ function getModuleDependencies(modulePath) {
function isModuleUsedElsewhere(modulePath, moduleName) {
return Object.keys(require.cache).some(path => {
const moduleObj = require.cache[path];
return moduleObj.children.some(child => child.id === modulePath && path !== modulePath);
// return moduleObj.children.some(child => child.id === modulePath && path !== modulePath);
return moduleObj.children.some(child => {
// let test = child.id === modulePath && path !== modulePath
// if (test)
// return test
return child.id === modulePath && path !== modulePath
});
});
}

Expand All @@ -77,17 +124,12 @@ function clearModuleCache(moduleName) {
const modulePath = require.resolve(moduleName);
const dependencies = getModuleDependencies(modulePath);

// Recursively clear dependencies from cache
dependencies.forEach(depPath => {
clearModuleCache(depPath);
});

// Check if the module is a dependency of other modules
const moduleObj = require.cache[modulePath];
if (moduleObj && moduleObj.parent) {
console.log(`Module ${moduleName} is a dependency of other modules.`);
return;
}
// const moduleObj = require.cache[modulePath];
// if (moduleObj && moduleObj.parent) {
// console.log(`Module ${moduleName} is a dependency of other modules.`);
// return;
// }

// Check if the module is used by other modules
if (isModuleUsedElsewhere(modulePath, moduleName)) {
Expand All @@ -98,34 +140,25 @@ function clearModuleCache(moduleName) {
// Remove the module from the cache
delete require.cache[modulePath];
console.log(`Module ${moduleName} has been removed from cache.`);
} catch (error) {
console.error(`Error clearing module cache for ${moduleName}: ${error.message}`);
}
}
// Recursively clear dependencies from cache
dependencies.forEach(depPath => {
clearModuleCache(depPath);
});

// Function to create the scripts directory if it doesn't exist
async function createScriptsDirectory() {
try {
await fs.mkdir(scriptsDirectory, { recursive: true });
console.log(`Scripts directory created at ${scriptsDirectory}`);
} catch (error) {
console.error('Error creating scripts directory:', error);
throw error; // Halt execution if directory creation fails
console.error(`Error clearing module cache for ${moduleName}: ${error.message}`);
}
}

// Call this function at the start of your application
createScriptsDirectory();

// Function to fetch script from database and save to disk
async function fetchScriptFromDatabaseAndSave(scriptId, pathname) {
async function fetchScriptFromDatabaseAndSave(moduleName, moduleConfig) {
let data = {
method: 'object.read',
array: 'files',
array: moduleConfig.array,
$filter: {
query: [
{ key: "host", value: [hostname, '*'], operator: "$in" },
{ key: "pathname", value: pathname, operator: "$eq" }
{ key: "host", value: [moduleConfig.object.hostname, '*'], operator: "$in" },
{ key: "pathname", value: moduleConfig.object.pathname, operator: "$eq" }
],
limit: 1
},
Expand All @@ -142,69 +175,10 @@ async function fetchScriptFromDatabaseAndSave(scriptId, pathname) {
}

// Save to disk for future use
const scriptPath = path.join(scriptsDirectory, `${scriptId}.js`);
const scriptPath = path.join(scriptsDirectory, `${moduleName}.js`);
await fs.writeFile(scriptPath, src);

return src;
}

// Map to track timeouts and contexts for each script
const scriptTimeouts = new Map();

// Function to execute a script with a debounce timeout
async function executeScriptWithTimeout(scriptId, pathname, timeoutDuration = 10000) {
let context;
let scriptContent;

// Check if the script is already loaded
if (scriptTimeouts.has(scriptId)) {
clearTimeout(scriptTimeouts.get(scriptId).timeout);
context = scriptTimeouts.get(scriptId).context;
} else {
// Check if script exists on disk, else fetch from database
const scriptPath = path.join(scriptsDirectory, `${scriptId}.js`);
try {
await fs.access(scriptPath);
scriptContent = await fs.readFile(scriptPath, 'utf8');
} catch {
scriptContent = await fetchScriptFromDatabaseAndSave(scriptId, pathname);
}

// Execute the script
context = new vm.createContext({});
const script = new vm.Script(scriptContent);
script.runInContext(context);
}

// Reset or set the timeout
const timeout = setTimeout(() => {
for (const key in context) {
if (context.hasOwnProperty(key)) {
delete context[key];
}
}
scriptTimeouts.delete(scriptId);
console.log(`Script ${scriptId} removed due to inactivity.`);
}, timeoutDuration);

// Update the map
scriptTimeouts.set(scriptId, { context, timeout });
}

// Example usage
const scriptId = 'unique-script-id';
const pathname = '/path/to/script'; // Set the appropriate pathname

executeScriptWithTimeout(scriptId, pathname, 10000).then(() => {
console.log(`Script ${scriptId} executed.`);
});


// Call this function at the start of your server
// generateExclusionList();

// Example usage
// const moduleName = 'your-module-name';
// clearModuleCache(moduleName);

module.exports = CoCreateLazyLoader;

0 comments on commit 8e0b9fc

Please sign in to comment.