在哪里存储我的节点时间表

我对Node / Express很陌生,我正在预约系统。 我希望我的用户预约他们想要的一天,我的系统会在准确的时间向他们发送通知。 我发现“node-schedule”模块对于这个任务非常有用,但是我不知道在哪里实现。 有没有办法将所有任务存储在我的app.js中,或者每当我点击某个终点时创build节点调度任务就足够了,例如:

router.get('/', function(req, res, next) { var j = schedule.scheduleJob(date, function(){ send notification(); }); res.send(200); } 

注意:我不想在我的sql表上运行一个常量来检查date

您需要使用SQLite ,运行您自己的数据库服务器(如MongoDB )或使用基于云的存储服务(如Amazon SimpleDb )写入本地文件来将应用程序数据保存到某种forms的永久存储中。

这些选项(以及其他许多选项)都有npm模块,可用于读取/写入/删除持久性数据。 有关示例,请参阅npmjs.com上的使用npm MongoDb , SQLite3和SimpleDb 。

UPDATE

根据您的评论如下:那么,你确实问你可以在哪里存储你的预定事件。 ;)

要坚持所有的计划事件,以便在服务器出现故障的情况下生存下来,您需要创build一个可存储的数据结构来表示它们,并为每个事件创build一个新的实例,并将其存储到永久存储器(MySQL)中。

通常情况下,您可以使用以下内容:

 { when:DateTime -- timestamp when the event should fire what:Action -- what this event should do args:Arguments -- arguments to pass to Action pending:Boolean=true -- if false, this event has already fired } 

初始化服务器时,您将查询持久存储的所有pending===true事件并使用结果,初始化node-schedule模块的实例。

当您的服务器运行时需要安排新事件时,您需要创build一个新的事件表示,将其写入永久性存储并使用它创build一个新的node-schedule实例。

最后, 对于客户的幸福最重要的是 ,当一个预定的事件成功完成时,就在你的事件处理器(上面提到的Action )完成之前,它需要将它正在处理的事件的持久版本标记为pending:false所以你不要任何事件不得超过一次。

举个例子:

  'use strict'; var scheduler = require('node-schedule'); /** * Storable Representation of a Scheduled Event * * @param {string|Date} when * @param {string} what * @param {array.<string>} [args=[]] * @param {boolean} [pending=true] * * @property {Date} PersistentEvent.when - the datetime this event should fire. * @property {string} PersistentEvent.what - the name of the action to run (must match key of PersistentEvent.Actions) * @property {array} PersistentEvent.args - args to pass to action event handler. * @property {boolean} PersistentEvent.pending - if true, this event has not yet fired. * * @constructor * * @example * * var PersistentEvent = require('PersistentEvent'), * mysql = require('mysql'), * conn = mysql.createConnection({ ... }); * * conn.connect(); * * // at some point when initializing your app... * * // assign your persistent storage connection... * PersistentEvent.setStore(conn); * * // load all pending event from persistent storage... * PersistentEvent.loadAll$(function (err) { * if (err) { * throw new Error('failed to load all PersistentEvents: ' + err); * } * * // from this point on, all persistent events are loaded and running. * * }); */ var PersistentEvent = function (when, what, args, pending) { // initialize PersistentEvent.Cache.push(this.init({ when: when, what: what, args: args, pending: pending })); }; // ==== PersistentEvent Static Methods ==== /** * Pre-defined action event handlers. * <p> * Where the property key will be used to match the PersistentEvent.what property, * and the property value is a event handler function that accepts an optional * array of args and a callback (provided by PersistentEvent.prototype.schedule) * </p> * * @property {object} * @property {function} Actions.doSomething * @property {function} Actions.doSomethingElse * * @static */ PersistentEvent.Actions = { doSomething: function (args, cb) { // defaults args = args || []; // TODO check specific args here ... var result = true, err = null; // do your action here, possibly with passed args cb(err, result); }, doSomethingElse: function (args, cb) { // defaults args = args || []; // TODO check specific args here ... var result = true, err = null; // do your action here, possibly with passed args cb(err, result); } }; /** * Cache of all PersistentEvents * * @type {Array.<PersistentEvent>} * @static */ PersistentEvent.Cache = []; // Data Management /** * Connection to persistent storage. * TODO - This should be abstracted to handle other engines that MySQL. * @property {object} * @static */ PersistentEvent.StorageConnection = null; /** * Sets the storage connection used to persist events. * * @param {object} storageConnection * @static */ PersistentEvent.setStore = function (storageConnection) { // set the persistent storage connection // TODO - check args here... // Note: this function isn't really needed unless you're using other kinds of storage engines // where you'd want to test what engine was used and mutate this interface accordingly. PersistentEvent.StorageConnection = storageConnection; }; /** * Saves a PersistentEvent to StorageConnection. * * @param {PersistentEvent} event - event to save * @param {function} cb - callback on complete * @static */ PersistentEvent.save$ = function (event, cb) { var conn = PersistentEvent.StorageConnection; if (null === conn) { throw new Error('requires a StorageConnection'); } // TODO - check for active connection here... // TODO - check args here... conn.query('INSERT INTO TABLE when = :when, what = :what, args = :args, pending = :pending', event, cb); }; /** * Loads all PersistentEvents from StorageConnection. * @param {function} cb -- callback on complete * @static */ PersistentEvent.loadAll$ = function (cb) { var conn = PersistentEvent.StorageConnection; if (null === conn) { throw new Error('requires a StorageConnection'); } // check for active connection here... // check args here... conn.query('QUERY * FROM TABLE WHERE pending = true', function (err, results) { if (err) { return cb(err); } results.forEach(function (result) { // TODO: check for existence of required fields here... var event = new PersistentEvent(result.when, result.what, result.args, true); event.schedule(); }); cb(null); }); }; // ==== PersistentEvent Methods ==== /** * Initialize an instance of PersistentEvent. * * @param {object} opts * @return {PersistentEvent} */ Event.prototype.init = function (opts) { // check args if ('object' !== typeof opts) { throw new Error('opts must be an object'); } // set defaults opts.args = opts.args || []; opts.pending = opts.pending || true; // convert string to Date, if required if ('string' === typeof opts.when) { opts.when = new Date(opts.when); } // check that opts contains needed properties if (!opts.when instanceof Date) { throw new Error('when must be a string representation of a Date or a Date object'); } if ('string' !== typeof opts.what) { throw new Error('what must be a string containing an action name'); } if (!Array.isArray(opts.args)) { throw new Error('args must be an array'); } if ('boolean' !== typeof opts.pending) { throw new Error('pending must be a boolean'); } // set our properties var self = this; Object.keys(opts).forEach(function (key) { if (opts.hasOwnProperty(key)) { self = opts[key]; } }); return this; }; /** * Override for Object.toString() * @returns {string} */ PersistentEvent.prototype.toString = function () { return JSON.stringify(this); }; /** * Schedule the event to run.<br/> * <em>Side-effect: saves event to persistent storage.</em> */ PersistentEvent.prototype.schedule = function () { var self = this, handler = Actions[this.what]; if ('function' !== typeof handler) { throw new Error('no handler found for action:' + this.what); } PersistentEvent.save$(self, function () { self._event = scheduler.scheduleJob(self.when, function () { handler(self.args, function (err, result) { if (err) { console.error('event ' + self + ' failed:' + err); } self.setComplete(); }); }); }); }; /** * Sets this event complete.<br/> * <em>Side-effect: saves event to persistent storage.</em> */ PersistentEvent.prototype.setComplete = function () { var self = this; delete this._event; this.pending = false; PersistentEvent.save$(this, function (err) { if (err) { console.error('failed to save event ' + self + ' :' + err); } }); }; 

请注意,这是一个第一遍样板,向您展示一种devise解决scheme的方法。 这需要您进一步努力运行。

你可以每天早上做一个cron工作,select当天所有的约会和时间安排。 这样你就必须在服务器负载很小的时候查询一次数据库。