fix (templates): tal-to-data OK.

This commit is contained in:
Rodrigo Rodriguez 2024-09-11 21:02:19 -03:00
parent 393c73c217
commit 7d8d4e4d6b
3 changed files with 66 additions and 91 deletions

View file

@ -607,7 +607,7 @@ export class GBDeployer implements IGBDeployer {
if (!GBConfigService.get('STORAGE_NAME')) { if (!GBConfigService.get('STORAGE_NAME')) {
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName); const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder); await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
} else { } else {
await this.downloadFolder(min, path.join('work', `${gbai}`), packageName); await this.downloadFolder(min, path.join('work', `${gbai}`), packageName);
} }

View file

@ -36,9 +36,8 @@
import { createRpcServer } from '@push-rpc/core'; import { createRpcServer } from '@push-rpc/core';
import AuthenticationContext from 'adal-node'; import AuthenticationContext from 'adal-node';
import arrayBufferToBuffer from 'arraybuffer-to-buffer'; import arrayBufferToBuffer from 'arraybuffer-to-buffer';
import { watch } from 'fs'; import { Semaphore } from 'async-mutex';
import debounce from 'lodash.debounce'; import { Mutex } from 'async-mutex';
import chokidar from 'chokidar'; import chokidar from 'chokidar';
import { import {
AutoSaveStateMiddleware, AutoSaveStateMiddleware,
@ -409,7 +408,7 @@ export class GBMinService {
const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest); const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest);
if (!(await GBUtil.exists(packageTeams))) { if (!(await GBUtil.exists(packageTeams))) {
const data = await this.deployer.getBotManifest(instance); const data = await this.deployer.getBotManifest(instance);
await fs.writeFile(packageTeams, data); await fs.writeFile(packageTeams, data);
} }
// Serves individual URL for each bot user interface. // Serves individual URL for each bot user interface.
@ -1117,7 +1116,7 @@ export class GBMinService {
const folder = `work/${path}/cache`; const folder = `work/${path}/cache`;
const filename = `${GBAdminService.generateUuid()}.png`; const filename = `${GBAdminService.generateUuid()}.png`;
await fs.writeFile(urlJoin(folder, filename), data); await fs.writeFile(urlJoin(folder, filename), data);
step.context.activity.text = urlJoin( step.context.activity.text = urlJoin(
GBServer.globals.publicAddress, GBServer.globals.publicAddress,
`${min.instance.botId}`, `${min.instance.botId}`,
@ -1305,7 +1304,7 @@ export class GBMinService {
buffer = arrayBufferToBuffer(await res.arrayBuffer()); buffer = arrayBufferToBuffer(await res.arrayBuffer());
} }
await fs.writeFile(localFileName, buffer); await fs.writeFile(localFileName, buffer);
return { return {
fileName: attachment.name, fileName: attachment.name,
@ -1743,64 +1742,42 @@ await fs.writeFile(localFileName, buffer);
createRpcServer(proxies, GBServer.globals.server.apiServer, opts); createRpcServer(proxies, GBServer.globals.server.apiServer, opts);
} }
// Map to track recent changes with timestamps // Map to track recent changes with timestamps
private recentChanges: Map<string, number> = new Map();
private async watchPackages(min: GBMinInstance, packageType) { private recentChanges: Set<string> = new Set();
private mutex: Mutex = new Mutex();
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
if (!GBConfigService.get('STORAGE_NAME')) { if (!GBConfigService.get('STORAGE_NAME')) {
const packagePath = GBUtil.getGBAIPath(min.botId, packageType); const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath); const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
const watcher = chokidar.watch(libraryPath, { const watcher = chokidar.watch(libraryPath, {
persistent: true, depth: 99 // Watch subdirectories
ignoreInitial: true, // Ignore initial add events
depth: 99, // Watch subdirectories
awaitWriteFinish: {
stabilityThreshold: 500, // Wait for 500ms to ensure file is written completely
}
}); });
const WRITE_INTERVAL = 5000; // 5 seconds interval const handleFileChange = async (filePath: string) => {
this.recentChanges.add(filePath);
// Function to handle file changes and prevent multiple calls within the 5-second window // Use mutex to ensure only one deployment runs at a time
const handleFileChange = async (filePath) => { await this.mutex.runExclusive(async () => {
const now = Date.now(); if (this.recentChanges.size > 0) {
try {
// Add or update the file in the recent changes list const workFolder = path.join('work', packagePath);
this.recentChanges.set(filePath, now); await this.deployer.deployPackage2(min, null, workFolder, true);
} catch (error) {
// Clean up entries older than 5 seconds GBLogEx.error(min, `Error deploying package: ${GBUtil.toYAML(error)}`);
for (const [key, timestamp] of this.recentChanges.entries()) { } finally {
if (now - timestamp > WRITE_INTERVAL) { this.recentChanges.clear();
this.recentChanges.delete(key); }
} }
} });
// If we have recent changes, deploy the package only once
if (this.recentChanges.size > 0) {
try {
const workFolder = path.join('work', packagePath);
await this.deployer.deployPackage2(min, null, workFolder, true);
} catch (error) {
GBLogEx.error(min, `Error deploying package: ${GBUtil.toYAML(error)}`);
}
// Delay further processing to prevent multiple deployments within 5 seconds
await new Promise(resolve => setTimeout(resolve, WRITE_INTERVAL));
// After the delay, clear only entries that were processed
this.recentChanges.clear();
}
}; };
// Watch for file changes // Watch for file changes
watcher.on('change', (filePath) => { watcher.on('change', filePath => {
handleFileChange(filePath).catch(error => console.error('Error processing file change:', error)); handleFileChange(filePath).catch(error => console.error('Error processing file change:', error));
}); });
} }
} }
} }

View file

@ -161,47 +161,45 @@ export class GBUtil {
} }
public static async copyIfNewerRecursive(src, dest) { public static async copyIfNewerRecursive(src, dest) {
// Check if the source exists
if (!(await GBUtil.exists(src))) { if (!(await GBUtil.exists(src))) {
console.error(`Source path "${src}" does not exist.`); return;
return;
} }
// Check if the source is a directory // Check if the source is a directory
if ((await fs.stat(src)).isDirectory()) { if ((await fs.stat(src)).isDirectory()) {
// Create the destination directory if it doesn't exist // Create the destination directory if it doesn't exist
if (!(await GBUtil.exists(dest))) { if (!(await GBUtil.exists(dest))) {
await fs.mkdir(dest, { recursive: true }); await fs.mkdir(dest, { recursive: true });
} }
// Read all files and directories in the source directory // Read all files and directories in the source directory
const entries = await fs.readdir(src); const entries = await fs.readdir(src);
for (let entry of entries) { for (let entry of entries) {
const srcEntry = path.join(src, entry); const srcEntry = path.join(src, entry);
const destEntry = path.join(dest, entry); const destEntry = path.join(dest, entry);
// Recursively copy each entry // Recursively copy each entry
await this.copyIfNewerRecursive(srcEntry, destEntry);
await this.copyIfNewerRecursive(srcEntry, destEntry);
}
} else {
// Source is a file, check if we need to copy it
if (await GBUtil.exists(dest)) {
const srcStat = await fs.stat(src);
const destStat = await fs.stat(dest);
// Copy only if the source file is newer than the destination file
if (srcStat.mtime > destStat.mtime) {
await fs.cp(src, dest, { force: true });
} }
} else { } else {
// Destination file doesn't exist, so copy it // Source is a file, check if we need to copy it
await fs.cp(src, dest, { force: true }); if (await GBUtil.exists(dest)) {
const srcStat = await fs.stat(src);
const destStat = await fs.stat(dest);
// Copy only if the source file is newer than the destination file
if (srcStat.mtime > destStat.mtime) {
await fs.cp(src, dest, { force: true });
}
} else {
// Destination file doesn't exist, so copy it
await fs.cp(src, dest, { force: true });
}
} }
}
} }
// Check if is a tree or flat object. // Check if is a tree or flat object.
public static hasSubObject(t) { public static hasSubObject(t) {
for (var key in t) { for (var key in t) {