mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-17 23:45:59 +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>
|
||||
|
||||
18
yarn.lock
18
yarn.lock
@@ -7882,6 +7882,14 @@ no-case@^2.2.0:
|
||||
dependencies:
|
||||
lower-case "^1.1.1"
|
||||
|
||||
node-cron@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/node-cron/-/node-cron-2.0.3.tgz#b9649784d0d6c00758410eef22fa54a10e3f602d"
|
||||
integrity sha512-eJI+QitXlwcgiZwNNSRbqsjeZMp5shyajMR81RZCqeW0ZDEj4zU9tpd4nTh/1JsBiKbF8d08FCewiipDmVIYjg==
|
||||
dependencies:
|
||||
opencollective-postinstall "^2.0.0"
|
||||
tz-offset "0.0.1"
|
||||
|
||||
node-fetch@^1.0.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||
@@ -8208,6 +8216,11 @@ open@^6.4.0:
|
||||
dependencies:
|
||||
is-wsl "^1.1.0"
|
||||
|
||||
opencollective-postinstall@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
|
||||
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
|
||||
|
||||
opn@^5.5.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
|
||||
@@ -11627,6 +11640,11 @@ typescript@^3.7.4, typescript@^3.7.5:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
|
||||
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
|
||||
|
||||
tz-offset@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tz-offset/-/tz-offset-0.0.1.tgz#fef920257024d3583ed9072a767721a18bdb8a76"
|
||||
integrity sha512-kMBmblijHJXyOpKzgDhKx9INYU4u4E1RPMB0HqmKSgWG8vEcf3exEfLh4FFfzd3xdQOw9EuIy/cP0akY6rHopQ==
|
||||
|
||||
ua-parser-js@^0.7.18:
|
||||
version "0.7.22"
|
||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3"
|
||||
|
||||
Reference in New Issue
Block a user