mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 22:43:58 +00:00
shell script scheduler
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
"lodash": "^4.17.15",
|
||||
"ncp": "^2.0.0",
|
||||
"nedb-promises": "^4.0.1",
|
||||
"node-cron": "^2.0.3",
|
||||
"tar": "^6.0.5",
|
||||
"uuid": "^3.4.0"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const { filesdir } = require('../utility/directories');
|
||||
const socket = require('../utility/socket');
|
||||
const scheduler = require('./scheduler');
|
||||
|
||||
function serialize(format, data) {
|
||||
if (format == 'text') return data;
|
||||
@@ -44,5 +45,8 @@ module.exports = {
|
||||
}
|
||||
await fs.writeFile(path.join(dir, file), serialize(format, data));
|
||||
socket.emitChanged(`files-changed-${folder}`);
|
||||
if (folder == 'shell') {
|
||||
scheduler.reload();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
41
packages/api/src/controllers/scheduler.js
Normal file
41
packages/api/src/controllers/scheduler.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const { filesdir } = require('../utility/directories');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const cron = require('node-cron');
|
||||
const runners = require('./runners');
|
||||
|
||||
const scheduleRegex = /\s*\/\/\s*@schedule\s+([^\n]+)\n/;
|
||||
|
||||
module.exports = {
|
||||
tasks: [],
|
||||
|
||||
async unload() {
|
||||
this.tasks.forEach((x) => x.destroy());
|
||||
this.tasks = [];
|
||||
},
|
||||
|
||||
async processFile(file) {
|
||||
const text = await fs.readFile(file, { encoding: 'utf-8' });
|
||||
const match = text.match(scheduleRegex);
|
||||
if (!match) return;
|
||||
const pattern = match[1];
|
||||
if (!cron.validate(pattern)) return;
|
||||
console.log(`Schedule script ${file} with pattern ${pattern}`);
|
||||
const task = cron.schedule(pattern, () => runners.start({ script: text }));
|
||||
this.tasks.push(task);
|
||||
},
|
||||
|
||||
async reload() {
|
||||
const shellDir = path.join(filesdir(), 'shell');
|
||||
await this.unload();
|
||||
if (!(await fs.exists(shellDir))) return;
|
||||
const files = await fs.readdir(shellDir);
|
||||
for (const file of files) {
|
||||
await this.processFile(path.join(shellDir, file));
|
||||
}
|
||||
},
|
||||
|
||||
async _init() {
|
||||
this.reload();
|
||||
},
|
||||
};
|
||||
@@ -24,6 +24,7 @@ const archive = require('./controllers/archive');
|
||||
const uploads = require('./controllers/uploads');
|
||||
const plugins = require('./controllers/plugins');
|
||||
const files = require('./controllers/files');
|
||||
const scheduler = require('./controllers/scheduler');
|
||||
|
||||
const { rundir } = require('./utility/directories');
|
||||
|
||||
@@ -69,6 +70,7 @@ function start(argument = null) {
|
||||
useController(app, '/uploads', uploads);
|
||||
useController(app, '/plugins', plugins);
|
||||
useController(app, '/files', files);
|
||||
useController(app, '/scheduler', scheduler);
|
||||
|
||||
if (process.env.PAGES_DIRECTORY) {
|
||||
app.use('/pages', express.static(process.env.PAGES_DIRECTORY));
|
||||
|
||||
@@ -32,9 +32,10 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
|
||||
const extensions = useExtensions();
|
||||
const { editorData, setEditorData, isLoading } = useEditorData({
|
||||
tabid,
|
||||
loadFromArgs: initialArgs && initialArgs.sqlTemplate
|
||||
? () => applySqlTemplate(initialArgs.sqlTemplate, extensions, { conid, database, ...other })
|
||||
: null,
|
||||
loadFromArgs:
|
||||
initialArgs && initialArgs.sqlTemplate
|
||||
? () => applySqlTemplate(initialArgs.sqlTemplate, extensions, { conid, database, ...other })
|
||||
: null,
|
||||
});
|
||||
|
||||
const editorRef = React.useRef(null);
|
||||
@@ -113,12 +114,13 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
|
||||
editorRef.current.editor.clearSelection();
|
||||
};
|
||||
|
||||
if (isLoading)
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div>
|
||||
<LoadingInfo message="Loading SQL script" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -15,6 +15,7 @@ import ImportExportModal from '../modals/ImportExportModal';
|
||||
import useEditorData from '../utility/useEditorData';
|
||||
import SaveTabModal from '../modals/SaveTabModal';
|
||||
import useModalState from '../modals/useModalState';
|
||||
import LoadingInfo from '../widgets/LoadingInfo';
|
||||
|
||||
const configRegex = /\s*\/\/\s*@ImportExportConfigurator\s*\n\s*\/\/\s*(\{[^\n]+\})\n/;
|
||||
const requireRegex = /\s*(\/\/\s*@require\s+[^\n]+)\n/g;
|
||||
@@ -22,7 +23,7 @@ const requireRegex = /\s*(\/\/\s*@require\s+[^\n]+)\n/g;
|
||||
export default function ShellTab({ tabid, tabVisible, toolbarPortalRef, ...other }) {
|
||||
const [busy, setBusy] = React.useState(false);
|
||||
const showModal = useShowModal();
|
||||
const { editorData, setEditorData } = useEditorData({ tabid });
|
||||
const { editorData, setEditorData, isLoading } = useEditorData({ tabid });
|
||||
const saveFileModalState = useModalState();
|
||||
|
||||
const setOpenedTabs = useSetOpenedTabs();
|
||||
@@ -89,6 +90,14 @@ export default function ShellTab({ tabid, tabVisible, toolbarPortalRef, ...other
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div>
|
||||
<LoadingInfo message="Loading shell script" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<VerticalSplitter>
|
||||
|
||||
Reference in New Issue
Block a user