Skip to content
This repository has been archived by the owner on Jun 15, 2022. It is now read-only.

Commit

Permalink
v1.0.7
Browse files Browse the repository at this point in the history
 - Compatibility with `Meteor@1.4.2`
 - ES6 modules and import support
 - Codebase updated with efficiency in mind
  • Loading branch information
dr-dimitru committed Nov 1, 2016
1 parent 1cb79c4 commit 49cbf06
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 97 deletions.
97 changes: 50 additions & 47 deletions .versions
Original file line number Diff line number Diff line change
@@ -1,47 +1,50 @@
babel-compiler@5.8.24_1
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
callback-hook@1.0.4
check@1.1.0
coffeescript@1.0.11
ddp@1.2.2
ddp-client@1.2.1
ddp-common@1.2.2
ddp-server@1.2.2
deps@1.0.9
diff-sequence@1.0.1
ecmascript@0.1.6
ecmascript-runtime@0.2.6
ejson@1.0.7
geojson-utils@1.0.4
html-tools@1.0.5
htmljs@1.0.5
id-map@1.0.4
jquery@1.11.4
logging@1.0.8
meteor@1.1.10
minimongo@1.0.10
mongo@1.1.3
mongo-id@1.0.1
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
ostrio:cron-jobs@1.0.6
promise@0.5.1
random@1.0.5
reactive-var@1.0.6
retry@1.0.4
routepolicy@1.0.6
sha@1.0.4
spacebars@1.0.7
spacebars-compiler@1.0.7
tracker@1.0.9
ui@1.0.8
underscore@1.0.4
webapp@1.2.3
webapp-hashing@1.0.5
allow-deny@1.0.5
babel-compiler@6.9.0
babel-runtime@0.1.10
base64@1.0.9
binary-heap@1.0.9
blaze@2.1.8
blaze-tools@1.0.9
boilerplate-generator@1.0.9
caching-compiler@1.1.6
callback-hook@1.0.9
check@1.2.3
coffeescript@1.2.3
ddp@1.2.5
ddp-client@1.2.5
ddp-common@1.2.5
ddp-server@1.2.6
deps@1.0.12
diff-sequence@1.0.6
ecmascript@0.5.7
ecmascript-runtime@0.3.12
ejson@1.0.12
geojson-utils@1.0.9
html-tools@1.0.10
htmljs@1.0.10
id-map@1.0.8
jquery@1.11.9
logging@1.1.14
meteor@1.2.16
minimongo@1.0.17
modules@0.7.5
modules-runtime@0.7.5
mongo@1.1.10
mongo-id@1.0.5
npm-mongo@1.5.45
observe-sequence@1.0.12
ordered-dict@1.0.8
ostrio:cron-jobs@1.0.7
promise@0.8.3
random@1.0.10
reactive-var@1.0.10
retry@1.0.7
routepolicy@1.0.11
sha@1.0.8
spacebars@1.0.12
spacebars-compiler@1.0.12
tracker@1.1.0
ui@1.0.11
underscore@1.0.9
webapp@1.3.10
webapp-hashing@1.0.9
60 changes: 44 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ Install:
meteor add ostrio:cron-jobs
```

ES6 Import:
======
```jsx
import { CRONjob } from 'meteor/ostrio:cron-jobs';
```

API:
========
`new CRONjob([prefix, resetOnInit])`:
Expand Down Expand Up @@ -49,8 +55,8 @@ var task = function (ready) {
ready();
};

CRON1.setInterval(task, 60*60*1000);
CRON2.setInterval(task, 60*60*2000);
CRON1.setInterval(task, 60*60*1000, 'task-1000');
CRON2.setInterval(task, 60*60*2000, 'task-2000');
```

Passing arguments (*not really fancy solution, sorry*):
Expand All @@ -71,12 +77,25 @@ var task1 = function (ready) {
task(1, globalVar, ready);
};

CRON.setInterval(taskB, 60*60*1000);
CRON.setInterval(task1, 60*60*1000);
CRON.setInterval(taskB, 60*60*1000, 'taskB');
CRON.setInterval(task1, 60*60*1000, 'task1');
```

Note: This library uses on function names and its contents, so after deploying new version of your application to server, you need to clean up old tasks:
```js
// Run directly in MongoDB console:
db.getCollection('__CRONjobs__').remove({});
// If you're using multiple CRONjob instances with prefix:
db.getCollection('__CRONjobs__PrefixHere').remove({});
```


#### `setInterval(func, delay, uid)`

- `func` {*Function*} - Function to call on schedule
- `delay` {*Number*} - Delay for first run and interval between further executions in milliseconds
- `uid` {*String*} - [Optional] recommended to set. Unique app-wide task id

#### `setInterval(func, delay)`
*Set task into interval execution loop. You can not set same function multiple times into interval.*
`ready()` *is passed as argument into function, and must be called in all tasks.*

Expand All @@ -93,8 +112,8 @@ var asyncTask = function (ready) {
});
};

CRON.setInterval(syncTask, 60*60*1000);
CRON.setInterval(asyncTask, 60*60*1000);
CRON.setInterval(syncTask, 60*60*1000, 'syncTask');
CRON.setInterval(asyncTask, 60*60*1000, 'asyncTask');
```

In this example, next task will not wait for current task is ready:
Expand All @@ -110,8 +129,8 @@ var asyncTask = function (ready) {
});
};

CRON.setInterval(syncTask, 60*60*1000);
CRON.setInterval(asyncTask, 60*60*1000);
CRON.setInterval(syncTask, 60*60*1000, 'syncTask');
CRON.setInterval(asyncTask, 60*60*1000, 'asyncTask');
```

In this example, we're assuming to have long running task, and execute it in a loop without delay, but after full execution:
Expand All @@ -130,10 +149,15 @@ var longRunningAsyncTask = function (ready) {
});
};

CRON.setInterval(longRunningAsyncTask, 0);
CRON.setInterval(longRunningAsyncTask, 0, 'longRunningAsyncTask');
```

#### `setTimeout(func, delay)`
#### `setTimeout(func, delay, uid)`

- `func` {*Function*} - Function to call on schedule
- `delay` {*Number*} - Delay in milliseconds
- `uid` {*String*} - [Optional] recommended to set. Unique app-wide task id

*Set task into timeout execution. You can not set same function multiple times into timeout.*
*`setTimeout` is useful for cluster - when you need to make sure task was executed only once.*
`ready()` *is passed as argument into function, and must be called in all tasks.*
Expand All @@ -150,11 +174,15 @@ var asyncTask = function (ready) {
});
};

CRON.setTimeout(syncTask, 60*60*1000);
CRON.setTimeout(asyncTask, 60*60*1000);
CRON.setTimeout(syncTask, 60*60*1000, 'syncTask');
CRON.setTimeout(asyncTask, 60*60*1000, 'asyncTask');
```

#### `setImmidiate(func)`
#### `setImmidiate(func, uid)`

- `func` {*Function*} - Function to execute
- `uid` {*String*} - [Optional] recommended to set. Unique app-wide task id

*Immediate execute function, and only once. You can not set same function multiple times into immediate execution.*
`setImmidiate` *is useful for cluster - when you need to execute function immediately and only once.*
`ready()` *is passed as argument into function, and must be called in all tasks.*
Expand All @@ -171,8 +199,8 @@ var asyncTask = function (ready) {
});
};

CRON.setImmidiate(syncTask);
CRON.setImmidiate(asyncTask);
CRON.setImmidiate(syncTask, 'syncTask');
CRON.setImmidiate(asyncTask, 'asyncTask');
```

#### `clearInterval(timer)`
Expand Down
90 changes: 60 additions & 30 deletions cron-jobs.coffee
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
NoOp =-> return
bound = Meteor.bindEnvironment (callback) -> return callback()

class CRONjob
constructor: (prefix = '', resetOnInit = false, @zombieTime = 900000) ->
Expand All @@ -13,61 +14,85 @@ class CRONjob
if resetOnInit
@collection.update {}, {$set: inProgress: false}, NoOp
@collection.remove {isInterval: false}, NoOp

@tasks = {}
@__poll()

__poll: ->
self = @
Meteor.setTimeout ->
cursor = self.collection.find
$or: [{
executeAt: $lte: new Date()
inProgress: false
}, {
executeAt: $lte: new Date((+new Date) - self.zombieTime)
inProgress: true
}]

count = cursor.count()
if count > 0
i = 0

cursor.forEach (task) ->
++i
if self.tasks?[task.uid]
self.__execute task
if i is count
self.__poll()
return
else
try
cursor = self.collection.find
$or: [{
executeAt: $lte: new Date()
inProgress: false
}, {
executeAt: $lte: new Date((+new Date) - self.zombieTime)
inProgress: true
}]

count = cursor.count()
if count > 0
i = 0

cursor.forEach (task) ->
++i
if self.tasks?[task.uid]
process.nextTick ->
bound ->
self.__execute task
return
return
if i is count
self.__poll()
return
else
self.__poll()
catch
self.__poll()
return
, Math.random() * (2500 - 1500) + 1500
, Math.random() * (850) + 150

setInterval: (func, delay) ->
setInterval: (func, delay, uid) ->
check func, Function
check delay, Number
check uid, String

throw new Meteor.Error 500, '[ostrio:cron-jobs] [setInterval] delay must be positive Number!' if delay < 0
uid = SHA256 'setInterval' + func

if uid
uid += 'setInterval'
else
uid ?= SHA256 'setInterval' + func

@tasks[uid] = func
@__addTask uid, true, delay
return uid

setTimeout: (func, delay) ->
setTimeout: (func, delay, uid) ->
check func, Function
check delay, Number
check uid, String

throw new Meteor.Error 500, '[ostrio:cron-jobs] [setTimeout] delay must be positive Number!' if delay < 0
uid = SHA256 'setTimeout' + func

if uid
uid += 'setTimeout'
else
uid = SHA256 'setTimeout' + func

@tasks[uid] = func
@__addTask uid, false, delay
return uid

setImmediate: (func) ->
setImmediate: (func, uid) ->
check func, Function
uid = SHA256 'setImmediate' + func
check uid, String

if uid
uid += 'setImmediate'
else
uid = SHA256 'setImmediate' + func

@tasks[uid] = func
@__addTask uid, false, 0
return uid
Expand Down Expand Up @@ -139,4 +164,9 @@ class CRONjob
console.warn 'Something went wrong with one of your tasks - it\'s is missing. Try to use different instances.'
console.trace()
return
return
return

###
Export the CRONjob class
###
`export { CRONjob }`
8 changes: 4 additions & 4 deletions package.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Package.describe({
name: 'ostrio:cron-jobs',
version: '1.0.6',
version: '1.0.7',
summary: 'Task scheduler. With support of cluster or multiple NodeJS instances.',
git: 'https://github.com/VeliovGroup/Meteor-CRON-jobs',
documentation: 'README.md'
});

Package.onUse(function(api) {
api.versionsFrom('1.2.1');
api.use(['coffeescript', 'mongo', 'check', 'sha'], 'server');
api.addFiles('cron-jobs.coffee', 'server');
api.versionsFrom('1.4');
api.use(['coffeescript', `ecmascript`, 'mongo', 'check', 'sha'], 'server');
api.mainModule('cron-jobs.coffee', 'server');
api.export('CRONjob');
});

0 comments on commit 49cbf06

Please sign in to comment.