vulcan 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/vulcan/cli.rb +20 -10
- data/lib/vulcan/version.rb +1 -1
- data/server/Procfile +1 -1
- data/server/bin/web +10 -0
- data/server/lib/cloudant.coffee +20 -0
- data/server/lib/logger.coffee +17 -0
- data/server/lib/on.coffee +10 -0
- data/server/lib/spawner.coffee +65 -0
- data/server/node_modules/coffee-script/CNAME +1 -0
- data/server/node_modules/coffee-script/LICENSE +22 -0
- data/server/node_modules/coffee-script/README +51 -0
- data/server/node_modules/coffee-script/Rakefile +78 -0
- data/server/node_modules/coffee-script/bin/cake +7 -0
- data/server/node_modules/coffee-script/bin/coffee +7 -0
- data/server/node_modules/coffee-script/extras/jsl.conf +44 -0
- data/server/node_modules/coffee-script/lib/coffee-script/browser.js +92 -0
- data/server/node_modules/coffee-script/lib/coffee-script/cake.js +111 -0
- data/server/node_modules/coffee-script/lib/coffee-script/coffee-script.js +167 -0
- data/server/node_modules/coffee-script/lib/coffee-script/command.js +500 -0
- data/server/node_modules/coffee-script/lib/coffee-script/grammar.js +606 -0
- data/server/node_modules/coffee-script/lib/coffee-script/helpers.js +77 -0
- data/server/node_modules/coffee-script/lib/coffee-script/index.js +11 -0
- data/server/node_modules/coffee-script/lib/coffee-script/lexer.js +788 -0
- data/server/node_modules/coffee-script/lib/coffee-script/nodes.js +2986 -0
- data/server/node_modules/coffee-script/lib/coffee-script/optparse.js +138 -0
- data/server/node_modules/coffee-script/lib/coffee-script/parser.js +683 -0
- data/server/node_modules/coffee-script/lib/coffee-script/repl.js +261 -0
- data/server/node_modules/coffee-script/lib/coffee-script/rewriter.js +349 -0
- data/server/node_modules/coffee-script/lib/coffee-script/scope.js +146 -0
- data/server/node_modules/coffee-script/package.json +55 -0
- data/server/node_modules/connect-form/History.md +0 -6
- data/server/node_modules/connect-form/lib/connect-form.js +2 -4
- data/server/node_modules/connect-form/node_modules/formidable/Readme.md +64 -36
- data/server/node_modules/connect-form/node_modules/formidable/lib/incoming_form.js +5 -1
- data/server/node_modules/connect-form/node_modules/formidable/package.json +20 -6
- data/server/node_modules/connect-form/node_modules/formidable/test/common.js +5 -6
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/file/funkyfilename.txt +1 -0
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +1 -1
- data/server/node_modules/connect-form/node_modules/formidable/test/{slow → integration}/test-fixtures.js +38 -33
- data/server/node_modules/connect-form/node_modules/formidable/test/legacy/simple/test-incoming-form.js +11 -0
- data/server/node_modules/connect-form/node_modules/formidable/test/run.js +1 -6
- data/server/node_modules/connect-form/node_modules/formidable/test/unit/test-incoming-form.js +63 -0
- data/server/node_modules/connect-form/package.json +27 -5
- data/server/node_modules/cradle/README.md +10 -10
- data/server/node_modules/cradle/lib/cradle.js +117 -523
- data/server/node_modules/cradle/lib/cradle/database/attachments.js +120 -0
- data/server/node_modules/cradle/lib/cradle/database/changes.js +56 -0
- data/server/node_modules/cradle/lib/cradle/database/documents.js +215 -0
- data/server/node_modules/cradle/lib/cradle/database/index.js +65 -0
- data/server/node_modules/cradle/lib/cradle/database/views.js +125 -0
- data/server/node_modules/cradle/node_modules/follow/LICENSE +202 -0
- data/server/node_modules/cradle/node_modules/follow/README.md +164 -0
- data/server/node_modules/cradle/node_modules/follow/Rakefile +54 -0
- data/server/node_modules/cradle/node_modules/follow/api.js +35 -0
- data/server/node_modules/cradle/node_modules/follow/browser/eventemitter2.js +453 -0
- data/server/node_modules/cradle/node_modules/follow/browser/export.js +78 -0
- data/server/node_modules/cradle/node_modules/follow/browser/index.html +14 -0
- data/server/node_modules/cradle/node_modules/follow/browser/jquery-1.6.1.min.js +18 -0
- data/server/node_modules/cradle/node_modules/follow/browser/log4js.js +46 -0
- data/server/node_modules/cradle/node_modules/follow/browser/main.js +92 -0
- data/server/node_modules/cradle/node_modules/follow/browser/querystring.js +28 -0
- data/server/node_modules/cradle/node_modules/follow/browser/request.jquery.js +237 -0
- data/server/node_modules/cradle/node_modules/follow/browser/require.js +33 -0
- data/server/node_modules/cradle/node_modules/follow/browser/util.js +28 -0
- data/server/node_modules/cradle/node_modules/follow/cli.js +101 -0
- data/server/node_modules/cradle/node_modules/follow/lib/feed.js +556 -0
- data/server/node_modules/cradle/node_modules/follow/lib/index.js +66 -0
- data/server/node_modules/cradle/node_modules/follow/lib/stream.js +305 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/LICENSE +55 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/README.md +285 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/main.js +618 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/mimetypes.js +146 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/oauth.js +34 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/package.json +42 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/googledoodle.png +0 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/run.sh +6 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/server.js +57 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-body.js +90 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-cookie.js +29 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-cookiejar.js +90 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-errors.js +30 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-oauth.js +109 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-pipes.js +167 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-proxy.js +39 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-timeout.js +87 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/uuid.js +19 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/vendor/cookie/index.js +55 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/vendor/cookie/jar.js +72 -0
- data/server/node_modules/cradle/node_modules/follow/package.json +45 -0
- data/server/node_modules/cradle/node_modules/follow/test/couch.js +153 -0
- data/server/node_modules/cradle/node_modules/follow/test/follow.js +136 -0
- data/server/node_modules/cradle/node_modules/follow/test/issues.js +178 -0
- data/server/node_modules/cradle/node_modules/follow/test/issues/10.js +24 -0
- data/server/node_modules/cradle/node_modules/follow/test/stream.js +493 -0
- data/server/node_modules/cradle/node_modules/request/LICENSE +55 -0
- data/server/node_modules/cradle/node_modules/request/README.md +287 -0
- data/server/node_modules/cradle/node_modules/request/forever.js +103 -0
- data/server/node_modules/cradle/node_modules/request/main.js +913 -0
- data/server/node_modules/cradle/node_modules/request/mimetypes.js +152 -0
- data/server/node_modules/cradle/node_modules/request/oauth.js +34 -0
- data/server/node_modules/cradle/node_modules/request/package.json +42 -0
- data/server/node_modules/cradle/node_modules/request/tests/googledoodle.png +0 -0
- data/server/node_modules/cradle/node_modules/request/tests/run.js +38 -0
- data/server/node_modules/cradle/node_modules/request/tests/server.js +82 -0
- data/server/node_modules/cradle/node_modules/request/tests/squid.conf +77 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.cnf +20 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.crl +0 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.crt +17 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.csr +13 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.key +18 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.srl +1 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.cnf +19 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.crt +16 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.csr +11 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.js +28 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.key +9 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/npm-ca.crt +16 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/test.crt +15 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/test.key +15 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-body.js +95 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-cookie.js +29 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-cookiejar.js +90 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-defaults.js +68 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-errors.js +37 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-headers.js +52 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-httpModule.js +94 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-https-strict.js +97 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-https.js +86 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-oauth.js +117 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-params.js +92 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-pipes.js +202 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-proxy.js +39 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-qs.js +28 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-redirect.js +154 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-timeout.js +87 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-toJSON.js +14 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-tunnel.js +61 -0
- data/server/node_modules/cradle/node_modules/request/tunnel.js +229 -0
- data/server/node_modules/cradle/node_modules/request/uuid.js +19 -0
- data/server/node_modules/cradle/node_modules/request/vendor/cookie/index.js +65 -0
- data/server/node_modules/cradle/node_modules/request/vendor/cookie/jar.js +72 -0
- data/server/node_modules/cradle/node_modules/vargs/package.json +33 -10
- data/server/node_modules/cradle/package.json +50 -12
- data/server/node_modules/cradle/test/cache-test.js +1 -4
- data/server/node_modules/cradle/test/connection-test.js +179 -0
- data/server/node_modules/cradle/test/database-attachment-test.js +344 -0
- data/server/node_modules/cradle/test/database-cache-test.js +132 -0
- data/server/node_modules/cradle/test/database-test.js +219 -0
- data/server/node_modules/cradle/test/database-view-test.js +141 -0
- data/server/node_modules/cradle/test/fixtures/databases.json +28 -1
- data/server/node_modules/cradle/test/helpers/seed.js +14 -5
- data/server/node_modules/cradle/test/response-test.js +1 -1
- data/server/node_modules/express/History.md +16 -0
- data/server/node_modules/express/bin/express +7 -6
- data/server/node_modules/express/lib-cov/application.js +510 -0
- data/server/node_modules/express/lib-cov/express.js +65 -0
- data/server/node_modules/express/lib-cov/middleware.js +54 -0
- data/server/node_modules/express/lib-cov/request.js +225 -0
- data/server/node_modules/express/lib-cov/response.js +611 -0
- data/server/node_modules/express/lib-cov/router/collection.js +40 -0
- data/server/node_modules/express/lib-cov/router/index.js +515 -0
- data/server/node_modules/express/lib-cov/router/methods.js +9 -0
- data/server/node_modules/express/lib-cov/router/route.js +68 -0
- data/server/node_modules/express/lib-cov/utils.js +151 -0
- data/server/node_modules/express/lib-cov/view.js +81 -0
- data/server/node_modules/express/lib/express.js +1 -1
- data/server/node_modules/express/lib/http.js +1 -2
- data/server/node_modules/express/lib/request.js +2 -2
- data/server/node_modules/express/lib/router/methods.js +10 -1
- data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
- data/server/node_modules/express/node_modules/connect/lib/http.js +3 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +0 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +1 -2
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +42 -25
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +1 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +14 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +11 -0
- data/server/node_modules/express/node_modules/connect/package.json +35 -7
- data/server/node_modules/express/node_modules/mime/package.json +30 -8
- data/server/node_modules/express/node_modules/mkdirp/README.markdown +35 -2
- data/server/node_modules/express/node_modules/mkdirp/examples/pow.js +1 -1
- data/server/node_modules/express/node_modules/mkdirp/index.js +72 -13
- data/server/node_modules/express/node_modules/mkdirp/package.json +39 -21
- data/server/node_modules/express/node_modules/mkdirp/test/chmod.js +38 -0
- data/server/node_modules/express/node_modules/mkdirp/test/clobber.js +37 -0
- data/server/node_modules/express/node_modules/mkdirp/test/perm.js +32 -0
- data/server/node_modules/express/node_modules/mkdirp/test/perm_sync.js +39 -0
- data/server/node_modules/express/node_modules/mkdirp/test/sync.js +27 -0
- data/server/node_modules/express/node_modules/mkdirp/test/umask.js +28 -0
- data/server/node_modules/express/node_modules/mkdirp/test/umask_sync.js +27 -0
- data/server/node_modules/express/node_modules/qs/History.md +10 -0
- data/server/node_modules/express/node_modules/qs/Readme.md +9 -2
- data/server/node_modules/express/node_modules/qs/examples.js +3 -0
- data/server/node_modules/express/node_modules/qs/lib/querystring.js +8 -6
- data/server/node_modules/express/node_modules/qs/package.json +26 -8
- data/server/node_modules/express/node_modules/qs/test/parse.js +13 -1
- data/server/node_modules/express/node_modules/qs/test/stringify.js +45 -37
- data/server/node_modules/express/package.json +55 -16
- data/server/node_modules/express/test.js +41 -0
- data/server/node_modules/knox/package.json +26 -4
- data/server/node_modules/node-uuid/package.json +40 -11
- data/server/node_modules/node-uuid/test/test.js +1 -1
- data/server/node_modules/nodemon/README.md +120 -0
- data/server/node_modules/nodemon/nodemon.js +518 -0
- data/server/node_modules/nodemon/nodemonignore.example +11 -0
- data/server/node_modules/nodemon/package.json +49 -0
- data/server/node_modules/restler/README.md +144 -94
- data/server/node_modules/restler/lib/multipartform.js +2 -0
- data/server/node_modules/restler/lib/restler.js +218 -61
- data/server/node_modules/restler/package.json +35 -8
- data/server/node_modules/restler/test/all.js +6 -1
- data/server/node_modules/restler/test/restler.js +624 -118
- data/server/package.json +14 -10
- data/server/web.coffee +64 -0
- data/server/web.js +15 -3
- metadata +170 -57
- data/server/index.js +0 -14
- data/server/node_modules/connect-form/LICENSE +0 -22
- data/server/node_modules/connect-form/index.js +0 -100
- data/server/node_modules/connect-form/node_modules/formidable/test/fast/test-incoming-form.js +0 -45
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/no-filename/generic.http +0 -13
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +0 -26
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +0 -24
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +0 -23
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +0 -24
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +0 -22
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +0 -22
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +0 -22
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/multi_video.upload +0 -0
- data/server/node_modules/cradle/Makefile +0 -10
- data/server/node_modules/cradle/test/cradle-test.js +0 -650
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +0 -13
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +0 -26
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +0 -23
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multi_video.upload +0 -0
- data/server/node_modules/express/node_modules/connect/test.js +0 -52
- data/server/node_modules/express/testing/foo/app.js +0 -35
- data/server/node_modules/express/testing/foo/package.json +0 -9
- data/server/node_modules/express/testing/foo/public/stylesheets/style.css +0 -8
- data/server/node_modules/express/testing/foo/routes/index.js +0 -10
- data/server/node_modules/express/testing/foo/views/index.jade +0 -2
- data/server/node_modules/express/testing/foo/views/layout.jade +0 -6
- data/server/node_modules/express/testing/index.js +0 -43
- data/server/node_modules/express/testing/public/test.txt +0 -2971
- data/server/node_modules/express/testing/views/page.html +0 -1
- data/server/node_modules/express/testing/views/page.jade +0 -3
- data/server/node_modules/express/testing/views/test.md +0 -1
- data/server/node_modules/express/testing/views/user/index.jade +0 -1
- data/server/node_modules/express/testing/views/user/list.jade +0 -1
- data/server/node_modules/knox/lib/knox/mime/index.js +0 -308
- data/server/node_modules/knox/lib/knox/mime/test.js +0 -59
- data/server/node_modules/node-uuid/test/benchmark-native +0 -0
- data/server/node_modules/on/index.js +0 -13
- data/server/node_modules/restler/test/test_helper.js +0 -163
- data/server/node_modules/spawner/index.js +0 -106
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
RequireJS 0.26.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
|
|
3
|
+
Available via the MIT or new BSD license.
|
|
4
|
+
see: http://github.com/jrburke/requirejs for details
|
|
5
|
+
*/
|
|
6
|
+
var requirejs,require,define;
|
|
7
|
+
(function(){function M(a){return $.call(a)==="[object Function]"}function E(a){return $.call(a)==="[object Array]"}function V(a,c,g){for(var e in c)if(!(e in J)&&(!(e in a)||g))a[e]=c[e];return d}function R(a,c,d){a=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+a);if(d)a.originalError=d;return a}function aa(a,c,d){var e,x,j;for(e=0;j=c[e];e++){j=typeof j==="string"?{name:j}:j;x=j.location;if(d&&(!x||x.indexOf("/")!==0&&x.indexOf(":")===-1))x=d+"/"+(x||j.name);a[j.name]={name:j.name,location:x||
|
|
8
|
+
j.name,main:(j.main||"main").replace(fa,"").replace(ba,"")}}}function W(a,d){a.holdReady?a.holdReady(d):d?a.readyWait+=1:a.ready(!0)}function ga(a){function c(b,h){var n,o;if(b&&b.charAt(0)==="."&&h){p.pkgs[h]?h=[h]:(h=h.split("/"),h=h.slice(0,h.length-1));n=b=h.concat(b.split("/"));var a;for(o=0;a=n[o];o++)if(a===".")n.splice(o,1),o-=1;else if(a==="..")if(o===1&&(n[2]===".."||n[0]===".."))break;else o>0&&(n.splice(o-1,2),o-=2);o=p.pkgs[n=b[0]];b=b.join("/");o&&b===n+"/"+o.main&&(b=n)}return b}function g(b,
|
|
9
|
+
h){var n=b?b.indexOf("!"):-1,o=null,a=h?h.name:null,ha=b,g,l;n!==-1&&(o=b.substring(0,n),b=b.substring(n+1,b.length));o&&(o=c(o,a));b&&(g=o?(n=m[o])?n.normalize?n.normalize(b,function(b){return c(b,a)}):c(b,a):"__$p"+a+"@"+(b||""):c(b,a),l=E[g],l||(l=d.toModuleUrl?d.toModuleUrl(f,g,h):f.nameToUrl(g,null,h),E[g]=l));return{prefix:o,name:g,parentMap:h,url:l,originalName:ha,fullName:o?o+"!"+(g||""):g}}function e(){var b=!0,h=p.priorityWait,n,a;if(h){for(a=0;n=h[a];a++)if(!s[n]){b=!1;break}b&&delete p.priorityWait}return b}
|
|
10
|
+
function x(b){return function(h){b.exports=h}}function j(b,h,n){return function(){var a=[].concat(ia.call(arguments,0)),d;if(n&&M(d=a[a.length-1]))d.__requireJsBuild=!0;a.push(h);return b.apply(null,a)}}function q(b,h){var a=j(f.require,b,h);V(a,{nameToUrl:j(f.nameToUrl,b),toUrl:j(f.toUrl,b),defined:j(f.requireDefined,b),specified:j(f.requireSpecified,b),ready:d.ready,isBrowser:d.isBrowser});if(d.paths)a.paths=d.paths;return a}function v(b){var h=b.prefix,a=b.fullName;y[a]||a in m||(h&&!K[h]&&(K[h]=
|
|
11
|
+
void 0,(S[h]||(S[h]=[])).push(b),(t[h]||(t[h]=[])).push({onDep:function(b){if(b===h){var a,n,d,c,f,e,j=S[h];if(j)for(d=0;a=j[d];d++)if(b=a.fullName,a=g(a.originalName,a.parentMap),a=a.fullName,n=t[b]||[],c=t[a],a!==b){b in y&&(delete y[b],y[a]=!0);t[a]=c?c.concat(n):n;delete t[b];for(c=0;c<n.length;c++){e=n[c].depArray;for(f=0;f<e.length;f++)e[f]===b&&(e[f]=a)}}delete S[h]}}}),v(g(h))),f.paused.push(b))}function w(b){var h,a,c;h=b.callback;var k=b.fullName,e=[],j=b.depArray;if(h&&M(h)){if(j)for(h=
|
|
12
|
+
0;h<j.length;h++)e.push(b.deps[j[h]]);if(p.catchError.define)try{a=d.execCb(k,b.callback,e,m[k])}catch(l){c=l}else a=d.execCb(k,b.callback,e,m[k]);if(k)b.cjsModule&&b.cjsModule.exports!==void 0?a=m[k]=b.cjsModule.exports:a===void 0&&b.usingExports?a=m[k]:m[k]=a}else k&&(a=m[k]=h);if(F[b.waitId])delete F[b.waitId],b.isDone=!0,f.waitCount-=1,f.waitCount===0&&(I=[]);if(c)return a=(k?g(k).url:"")||c.fileName||c.sourceURL,c=R("defineerror",'Error evaluating module "'+k+'" at location "'+a+'":\n'+c+"\nfileName:"+
|
|
13
|
+
a+"\nlineNumber: "+(c.lineNumber||c.line),c),c.moduleName=k,d.onError(c);if(k&&(c=t[k])){for(h=0;h<c.length;h++)c[h].onDep(k,a);delete t[k]}}function z(b,a,c,d){var b=g(b,d),k=b.name,e=b.fullName,j={},l={waitId:k||ja+Q++,depCount:0,depMax:0,prefix:b.prefix,name:k,fullName:e,deps:{},depArray:a,callback:c,onDep:function(b,a){b in l.deps||(l.deps[b]=a,l.depCount+=1,l.depCount===l.depMax&&w(l))}},i,r;if(e){if(e in m||s[e]===!0||e==="jquery"&&p.jQuery&&p.jQuery!==c().fn.jquery)return;y[e]=!0;s[e]=!0;e===
|
|
14
|
+
"jquery"&&c&&T(c())}for(c=0;c<a.length;c++)if(i=a[c])i=g(i,k?b:d),r=i.fullName,a[c]=r,r==="require"?l.deps[r]=q(b):r==="exports"?(l.deps[r]=m[e]={},l.usingExports=!0):r==="module"?(l.cjsModule=i=l.deps[r]={id:k,uri:k?f.nameToUrl(k,null,d):void 0,exports:m[e]},i.setExports=x(i)):r in m&&!(r in F)?l.deps[r]=m[r]:j[r]||(l.depMax+=1,v(i),(t[r]||(t[r]=[])).push(l),j[r]=!0);l.depCount===l.depMax?w(l):(F[l.waitId]=l,I.push(l),f.waitCount+=1)}function u(b){z.apply(null,b);s[b[0]]=!0}function C(b,a){if(!b.isDone){var c=
|
|
15
|
+
b.fullName,d=b.depArray,f,e;if(c){if(a[c])return m[c];a[c]=!0}for(e=0;e<d.length;e++)if((f=d[e])&&!b.deps[f]&&F[f])b.onDep(f,C(F[f],a));return c?m[c]:void 0}}function A(){var b=p.waitSeconds*1E3,a=b&&f.startTime+b<(new Date).getTime(),b="",c=!1,g=!1,k;if(!(f.pausedCount>0)){if(p.priorityWait)if(e())G();else return;for(k in s)if(!(k in J)&&(c=!0,!s[k]))if(a)b+=k+" ";else{g=!0;break}if(c||f.waitCount){if(a&&b)return k=R("timeout","Load timeout for modules: "+b),k.requireType="timeout",k.requireModules=
|
|
16
|
+
b,d.onError(k);if(g||f.scriptCount){if((B||ca)&&!X)X=setTimeout(function(){X=0;A()},50)}else{if(f.waitCount){for(H=0;b=I[H];H++)C(b,{});Y<5&&(Y+=1,A())}Y=0;d.checkReadyState()}}}}function D(b,a){var c=a.name,e=a.fullName,g;if(!(e in m||e in s))K[b]||(K[b]=m[b]),s[e]||(s[e]=!1),g=function(g){if(d.onPluginLoad)d.onPluginLoad(f,b,c,g);w({prefix:a.prefix,name:a.name,fullName:a.fullName,callback:function(){return g}});s[e]=!0},g.fromText=function(b,a){var c=N;f.loaded[b]=!1;f.scriptCount+=1;c&&(N=!1);
|
|
17
|
+
d.exec(a);c&&(N=!0);f.completeLoad(b)},K[b].load(c,q(a.parentMap,!0),g,p)}function L(b){b.prefix&&b.name&&b.name.indexOf("__$p")===0&&m[b.prefix]&&(b=g(b.originalName,b.parentMap));var a=b.prefix,c=b.fullName,e=f.urlFetched;!y[c]&&!s[c]&&(y[c]=!0,a?m[a]?D(a,b):(O[a]||(O[a]=[],(t[a]||(t[a]=[])).push({onDep:function(b){if(b===a){for(var c,d=O[a],b=0;b<d.length;b++)c=d[b],D(a,g(c.originalName,c.parentMap));delete O[a]}}})),O[a].push(b)):e[b.url]||(d.load(f,c,b.url),e[b.url]=!0))}var f,G,p={waitSeconds:7,
|
|
18
|
+
baseUrl:i.baseUrl||"./",paths:{},pkgs:{},catchError:{}},P=[],y={require:!0,exports:!0,module:!0},E={},m={},s={},F={},I=[],Q=0,t={},K={},O={},Z=0,S={};T=function(b){if(!f.jQuery&&(b=b||(typeof jQuery!=="undefined"?jQuery:null))&&!(p.jQuery&&b.fn.jquery!==p.jQuery)&&("holdReady"in b||"readyWait"in b))if(f.jQuery=b,u(["jquery",[],function(){return jQuery}]),f.scriptCount)W(b,!0),f.jQueryIncremented=!0};G=function(){var b,a,c;Z+=1;if(f.scriptCount<=0)f.scriptCount=0;for(;P.length;)if(b=P.shift(),b[0]===
|
|
19
|
+
null)return d.onError(R("mismatch","Mismatched anonymous define() module: "+b[b.length-1]));else u(b);if(!p.priorityWait||e())for(;f.paused.length;){c=f.paused;f.pausedCount+=c.length;f.paused=[];for(a=0;b=c[a];a++)L(b);f.startTime=(new Date).getTime();f.pausedCount-=c.length}Z===1&&A();Z-=1};f={contextName:a,config:p,defQueue:P,waiting:F,waitCount:0,specified:y,loaded:s,urlMap:E,scriptCount:0,urlFetched:{},defined:m,paused:[],pausedCount:0,plugins:K,managerCallbacks:t,makeModuleMap:g,normalize:c,
|
|
20
|
+
configure:function(b){var a,c,e;b.baseUrl&&b.baseUrl.charAt(b.baseUrl.length-1)!=="/"&&(b.baseUrl+="/");a=p.paths;e=p.pkgs;V(p,b,!0);if(b.paths){for(c in b.paths)c in J||(a[c]=b.paths[c]);p.paths=a}if((a=b.packagePaths)||b.packages){if(a)for(c in a)c in J||aa(e,a[c],c);b.packages&&aa(e,b.packages);p.pkgs=e}if(b.priority)c=f.requireWait,f.requireWait=!1,f.takeGlobalQueue(),G(),f.require(b.priority),G(),f.requireWait=c,p.priorityWait=b.priority;if(b.deps||b.callback)f.require(b.deps||[],b.callback);
|
|
21
|
+
b.ready&&d.ready(b.ready)},requireDefined:function(b,a){return g(b,a).fullName in m},requireSpecified:function(b,a){return g(b,a).fullName in y},require:function(b,c,e){if(typeof b==="string"){if(d.get)return d.get(f,b,c);c=g(b,c);b=c.fullName;return!(b in m)?d.onError(R("notloaded","Module name '"+c.fullName+"' has not been loaded yet for context: "+a)):m[b]}z(null,b,c,e);if(!f.requireWait)for(;!f.scriptCount&&f.paused.length;)f.takeGlobalQueue(),G();return f.require},takeGlobalQueue:function(){U.length&&
|
|
22
|
+
(ka.apply(f.defQueue,[f.defQueue.length-1,0].concat(U)),U=[])},completeLoad:function(b){var a;for(f.takeGlobalQueue();P.length;)if(a=P.shift(),a[0]===null){a[0]=b;break}else if(a[0]===b)break;else u(a),a=null;a?u(a):u([b,[],b==="jquery"&&typeof jQuery!=="undefined"?function(){return jQuery}:null]);s[b]=!0;T();d.isAsync&&(f.scriptCount-=1);G();d.isAsync||(f.scriptCount-=1)},toUrl:function(b,a){var c=b.lastIndexOf("."),d=null;c!==-1&&(d=b.substring(c,b.length),b=b.substring(0,c));return f.nameToUrl(b,
|
|
23
|
+
d,a)},nameToUrl:function(b,a,e){var g,j,i,m,l=f.config,b=c(b,e&&e.fullName);if(d.jsExtRegExp.test(b))a=b+(a?a:"");else{g=l.paths;j=l.pkgs;e=b.split("/");for(m=e.length;m>0;m--)if(i=e.slice(0,m).join("/"),g[i]){e.splice(0,m,g[i]);break}else if(i=j[i]){b=b===i.name?i.location+"/"+i.main:i.location;e.splice(0,m,b);break}a=e.join("/")+(a||".js");a=(a.charAt(0)==="/"||a.match(/^\w+:/)?"":l.baseUrl)+a}return l.urlArgs?a+((a.indexOf("?")===-1?"?":"&")+l.urlArgs):a}};f.jQueryCheck=T;f.resume=G;return f}function la(){var a,
|
|
24
|
+
c,d;if(C&&C.readyState==="interactive")return C;a=document.getElementsByTagName("script");for(c=a.length-1;c>-1&&(d=a[c]);c--)if(d.readyState==="interactive")return C=d;return null}var ma=/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,na=/require\(\s*["']([^'"\s]+)["']\s*\)/g,fa=/^\.\//,ba=/\.js$/,$=Object.prototype.toString,q=Array.prototype,ia=q.slice,ka=q.splice,B=!!(typeof window!=="undefined"&&navigator&&document),ca=!B&&typeof importScripts!=="undefined",oa=B&&navigator.platform==="PLAYSTATION 3"?/^complete$/:
|
|
25
|
+
/^(complete|loaded)$/,da=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",ja="_r@@",J={},z={},U=[],C=null,Y=0,N=!1,d,q={},I,i,u,L,v,A,D,H,Q,ea,w,T,X;if(typeof define==="undefined"){if(typeof requirejs!=="undefined")if(M(requirejs))return;else q=requirejs,requirejs=void 0;typeof require!=="undefined"&&!M(require)&&(q=require,require=void 0);d=requirejs=function(a,c,d){var e="_",i;!E(a)&&typeof a!=="string"&&(i=a,E(c)?(a=c,c=d):a=[]);if(i&&i.context)e=i.context;d=z[e]||(z[e]=ga(e));i&&
|
|
26
|
+
d.configure(i);return d.require(a,c)};d.config=function(a){return d(a)};typeof require==="undefined"&&(require=d);d.toUrl=function(a){return z._.toUrl(a)};d.version="0.26.0";d.isArray=E;d.isFunction=M;d.mixin=V;d.jsExtRegExp=/^\/|:|\?|\.js$/;i=d.s={contexts:z,skipAsync:{},isPageLoaded:!B,readyCalls:[]};if(d.isAsync=d.isBrowser=B)if(u=i.head=document.getElementsByTagName("head")[0],L=document.getElementsByTagName("base")[0])u=i.head=L.parentNode;d.onError=function(a){throw a;};d.load=function(a,c,
|
|
27
|
+
g){var e=a.loaded;e[c]||(e[c]=!1);a.scriptCount+=1;d.attach(g,a,c);if(a.jQuery&&!a.jQueryIncremented)W(a.jQuery,!0),a.jQueryIncremented=!0};define=d.def=function(a,c,g){var e,i;typeof a!=="string"&&(g=c,c=a,a=null);d.isArray(c)||(g=c,c=[]);!a&&!c.length&&d.isFunction(g)&&g.length&&(g.toString().replace(ma,"").replace(na,function(a,d){c.push(d)}),c=(g.length===1?["require"]:["require","exports","module"]).concat(c));if(N&&(e=I||la()))a||(a=e.getAttribute("data-requiremodule")),i=z[e.getAttribute("data-requirecontext")];
|
|
28
|
+
(i?i.defQueue:U).push([a,c,g])};define.amd={multiversion:!0,plugins:!0,jQuery:!0};d.exec=function(a){return eval(a)};d.execCb=function(a,c,d,e){return c.apply(e,d)};d.onScriptLoad=function(a){var c=a.currentTarget||a.srcElement,g;if(a.type==="load"||oa.test(c.readyState))C=null,a=c.getAttribute("data-requirecontext"),g=c.getAttribute("data-requiremodule"),z[a].completeLoad(g),c.detachEvent&&!da?c.detachEvent("onreadystatechange",d.onScriptLoad):c.removeEventListener("load",d.onScriptLoad,!1)};d.attach=
|
|
29
|
+
function(a,c,g,e,q){var j;if(B)return e=e||d.onScriptLoad,j=c&&c.config&&c.config.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),j.type=q||"text/javascript",j.charset="utf-8",j.async=!i.skipAsync[a],c&&j.setAttribute("data-requirecontext",c.contextName),j.setAttribute("data-requiremodule",g),j.attachEvent&&!da?(N=!0,j.attachEvent("onreadystatechange",e)):j.addEventListener("load",e,!1),j.src=a,I=j,L?u.insertBefore(j,L):u.appendChild(j),
|
|
30
|
+
I=null,j;else if(ca)e=c.loaded,e[g]=!1,importScripts(a),c.completeLoad(g);return null};if(B){v=document.getElementsByTagName("script");for(H=v.length-1;H>-1&&(A=v[H]);H--){if(!u)u=A.parentNode;if(D=A.getAttribute("data-main")){if(!q.baseUrl)v=D.split("/"),A=v.pop(),v=v.length?v.join("/")+"/":"./",q.baseUrl=v,D=A.replace(ba,"");q.deps=q.deps?q.deps.concat(D):[D];break}}}i.baseUrl=q.baseUrl;d.pageLoaded=function(){if(!i.isPageLoaded){i.isPageLoaded=!0;Q&&clearInterval(Q);if(ea)document.readyState="complete";
|
|
31
|
+
d.callReady()}};d.checkReadyState=function(){var a=i.contexts,c;for(c in a)if(!(c in J)&&a[c].waitCount)return;i.isDone=!0;d.callReady()};d.callReady=function(){var a=i.readyCalls,c,d,e;if(i.isPageLoaded&&i.isDone){if(a.length){i.readyCalls=[];for(c=0;d=a[c];c++)d()}a=i.contexts;for(e in a)if(!(e in J)&&(c=a[e],c.jQueryIncremented))W(c.jQuery,!1),c.jQueryIncremented=!1}};d.ready=function(a){i.isPageLoaded&&i.isDone?a():i.readyCalls.push(a);return d};if(B){if(document.addEventListener){if(document.addEventListener("DOMContentLoaded",
|
|
32
|
+
d.pageLoaded,!1),window.addEventListener("load",d.pageLoaded,!1),!document.readyState)ea=!0,document.readyState="loading"}else window.attachEvent&&(window.attachEvent("onload",d.pageLoaded),self===self.top&&(Q=setInterval(function(){try{document.body&&(document.documentElement.doScroll("left"),d.pageLoaded())}catch(a){}},30)));document.readyState==="complete"&&d.pageLoaded()}d(q);if(d.isAsync&&typeof setTimeout!=="undefined")w=i.contexts[q.context||"_"],w.requireWait=!0,setTimeout(function(){w.requireWait=
|
|
33
|
+
!1;w.takeGlobalQueue();w.jQueryCheck();w.scriptCount||w.resume();d.checkReadyState()},0)}})();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
define([], function() {
|
|
2
|
+
var exports = {};
|
|
3
|
+
|
|
4
|
+
exports.inspect = JSON.stringify;
|
|
5
|
+
|
|
6
|
+
// Copy from Node
|
|
7
|
+
/**
|
|
8
|
+
* Inherit the prototype methods from one constructor into another.
|
|
9
|
+
*
|
|
10
|
+
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|
11
|
+
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|
12
|
+
* during bootstrapping this function needs to be revritten using some native
|
|
13
|
+
* functions as prototype setup using normal JavaScript does not work as
|
|
14
|
+
* expected during bootstrapping (see mirror.js in r114903).
|
|
15
|
+
*
|
|
16
|
+
* @param {function} ctor Constructor function which needs to inherit the
|
|
17
|
+
* prototype.
|
|
18
|
+
* @param {function} superCtor Constructor function to inherit prototype from.
|
|
19
|
+
*/
|
|
20
|
+
exports.inherits = function(ctor, superCtor) {
|
|
21
|
+
ctor.super_ = superCtor;
|
|
22
|
+
ctor.prototype = Object.create(superCtor.prototype, {
|
|
23
|
+
constructor: { value: ctor, enumerable: false }
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return exports;
|
|
28
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The follow command-line interface.
|
|
3
|
+
//
|
|
4
|
+
// Copyright 2011 Iris Couch
|
|
5
|
+
//
|
|
6
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
// you may not use this file except in compliance with the License.
|
|
8
|
+
// You may obtain a copy of the License at
|
|
9
|
+
//
|
|
10
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
//
|
|
12
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
// See the License for the specific language governing permissions and
|
|
16
|
+
// limitations under the License.
|
|
17
|
+
|
|
18
|
+
var lib = require('./lib')
|
|
19
|
+
, couch_changes = require('./api')
|
|
20
|
+
;
|
|
21
|
+
|
|
22
|
+
function puts(str) {
|
|
23
|
+
process.stdout.write(str + "\n");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function main() {
|
|
27
|
+
var db = require.isBrowser ? (process.env.db || '/_users') : process.argv[2];
|
|
28
|
+
puts('Watching: ' + db);
|
|
29
|
+
|
|
30
|
+
var feed = new couch_changes.Feed();
|
|
31
|
+
feed.db = db;
|
|
32
|
+
feed.since = (process.env.since === 'now') ? 'now' : parseInt(process.env.since || '0');
|
|
33
|
+
|
|
34
|
+
feed.heartbeat = (process.env.heartbeat || '3000').replace(/s$/, '000');
|
|
35
|
+
feed.heartbeat = parseInt(feed.heartbeat);
|
|
36
|
+
|
|
37
|
+
if(require.isBrowser)
|
|
38
|
+
feed.feed = 'longpoll';
|
|
39
|
+
if(process.env.host)
|
|
40
|
+
feed.headers.host = process.env.host;
|
|
41
|
+
if(process.env.inactivity)
|
|
42
|
+
feed.inactivity_ms = parseInt(process.env.inactivity);
|
|
43
|
+
if(process.env.limit)
|
|
44
|
+
feed.limit = parseInt(process.env.limit);
|
|
45
|
+
|
|
46
|
+
feed.query_params.pid = process.pid;
|
|
47
|
+
feed.filter = process.env.filter || example_filter;
|
|
48
|
+
function example_filter(doc, req) {
|
|
49
|
+
// This is a local filter. It runs on the client side.
|
|
50
|
+
var label = 'Filter ' + (req.query.pid || '::');
|
|
51
|
+
|
|
52
|
+
if(process.env.show_doc)
|
|
53
|
+
console.log(label + ' doc: ' + JSON.stringify(doc));
|
|
54
|
+
if(process.env.show_req)
|
|
55
|
+
console.log(label + ' for ' + doc._id + ' req: ' + JSON.stringify(req));
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
feed.on('confirm', function() {
|
|
60
|
+
puts('Database confirmed: ' + db);
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
feed.on('change', function(change) {
|
|
64
|
+
puts('Change:' + JSON.stringify(change));
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
feed.on('timeout', function(state) {
|
|
68
|
+
var seconds = state.elapsed_ms / 1000;
|
|
69
|
+
var hb = state.heartbeat / 1000;
|
|
70
|
+
puts('Timeout after ' + seconds + 's inactive, heartbeat=' + hb + 's');
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
feed.on('retry', function(state) {
|
|
74
|
+
if(require.isBrowser)
|
|
75
|
+
puts('Long polling since ' + state.since);
|
|
76
|
+
else
|
|
77
|
+
puts('Retry since ' + state.since + ' after ' + state.after + 'ms');
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
feed.on('response', function() {
|
|
81
|
+
puts('Streaming response:');
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
feed.on('error', function(er) {
|
|
85
|
+
//console.error(er);
|
|
86
|
+
console.error('Changes error ============\n' + er.stack);
|
|
87
|
+
setTimeout(function() { process.exit(0) }, 100);
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
process.on('uncaughtException', function(er) {
|
|
91
|
+
puts('========= UNCAUGHT EXCEPTION; This is bad');
|
|
92
|
+
puts(er.stack);
|
|
93
|
+
setTimeout(function() { process.exit(1) }, 100);
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
feed.follow();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.main = main;
|
|
100
|
+
if(!require.isBrowser && process.argv[1] == module.filename)
|
|
101
|
+
main();
|
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
// Core routines for event emitters
|
|
2
|
+
//
|
|
3
|
+
// Copyright 2011 Iris Couch
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
var lib = require('../lib')
|
|
18
|
+
, util = require('util')
|
|
19
|
+
, events = require('events')
|
|
20
|
+
, request = require('request')
|
|
21
|
+
, Changes = require('./stream').Changes
|
|
22
|
+
, querystring = require('querystring')
|
|
23
|
+
|
|
24
|
+
// Use the library timeout functions, primarily so the test suite can catch errors.
|
|
25
|
+
var setTimeout = lib.setTimeout
|
|
26
|
+
, clearTimeout = lib.clearTimeout
|
|
27
|
+
|
|
28
|
+
var DEFAULT_HEARTBEAT = 30000;
|
|
29
|
+
var HEARTBEAT_TIMEOUT_COEFFICIENT = 1.25; // E.g. heartbeat 1000ms would trigger a timeout after 1250ms of no heartbeat.
|
|
30
|
+
var DEFAULT_MAX_RETRY_SECONDS = 60 * 60;
|
|
31
|
+
var INITIAL_RETRY_DELAY = 1000;
|
|
32
|
+
|
|
33
|
+
var FEED_PARAMETERS = ['since', 'limit', 'feed', 'heartbeat', 'filter', 'include_docs'];
|
|
34
|
+
|
|
35
|
+
var EventEmitter = events.EventEmitter2 || events.EventEmitter;
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
util.inherits(Feed, EventEmitter);
|
|
39
|
+
function Feed (opts) {
|
|
40
|
+
var self = this;
|
|
41
|
+
EventEmitter.call(self);
|
|
42
|
+
|
|
43
|
+
self.feed = 'continuous';
|
|
44
|
+
self.heartbeat = DEFAULT_HEARTBEAT;
|
|
45
|
+
self.max_retry_seconds = DEFAULT_MAX_RETRY_SECONDS;
|
|
46
|
+
self.inactivity_ms = null;
|
|
47
|
+
|
|
48
|
+
self.headers = {};
|
|
49
|
+
self.request = {}; // Extra options for potentially future versions of request. The caller can supply them.
|
|
50
|
+
|
|
51
|
+
self.since = 0;
|
|
52
|
+
self.caught_up = false
|
|
53
|
+
self.retry_delay = INITIAL_RETRY_DELAY; // ms
|
|
54
|
+
|
|
55
|
+
self.query_params = {}; // Extra `req.query` values for filter functions
|
|
56
|
+
|
|
57
|
+
opts = opts || {};
|
|
58
|
+
if(typeof opts === 'string')
|
|
59
|
+
opts = {'db': opts};
|
|
60
|
+
Object.keys(opts).forEach(function(key) {
|
|
61
|
+
self[key] = opts[key];
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
self.pending = { request : null
|
|
65
|
+
, activity_at : null
|
|
66
|
+
};
|
|
67
|
+
} // Feed
|
|
68
|
+
|
|
69
|
+
Feed.prototype.start =
|
|
70
|
+
Feed.prototype.follow = function follow_feed() {
|
|
71
|
+
var self = this;
|
|
72
|
+
|
|
73
|
+
if(!self.db)
|
|
74
|
+
throw new Error('Database URL required');
|
|
75
|
+
|
|
76
|
+
if(self.feed !== 'continuous' && self.feed !== 'longpoll')
|
|
77
|
+
throw new Error('The only valid feed options are "continuous" and "longpoll"');
|
|
78
|
+
|
|
79
|
+
if(typeof self.heartbeat !== 'number')
|
|
80
|
+
throw new Error('Required "heartbeat" value');
|
|
81
|
+
|
|
82
|
+
self.log = lib.log4js.getLogger(self.db);
|
|
83
|
+
self.log.setLevel(process.env.follow_log_level || "info");
|
|
84
|
+
|
|
85
|
+
self.emit('start');
|
|
86
|
+
return self.confirm();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Feed.prototype.confirm = function confirm_feed() {
|
|
90
|
+
var self = this;
|
|
91
|
+
|
|
92
|
+
self.db_safe = lib.scrub_creds(self.db);
|
|
93
|
+
|
|
94
|
+
self.log.debug('Checking database: ' + self.db_safe);
|
|
95
|
+
|
|
96
|
+
var confirm_timeout = self.heartbeat * 3; // Give it time to look up the name, connect, etc.
|
|
97
|
+
var timeout_id = setTimeout(function() {
|
|
98
|
+
return self.die(new Error('Timeout confirming database: ' + self.db_safe));
|
|
99
|
+
}, confirm_timeout);
|
|
100
|
+
|
|
101
|
+
var headers = lib.JP(lib.JS(self.headers));
|
|
102
|
+
headers.accept = 'application/json';
|
|
103
|
+
|
|
104
|
+
var req = request({'uri':self.db, 'headers':headers}, db_response)
|
|
105
|
+
self.emit('confirm_request', req)
|
|
106
|
+
|
|
107
|
+
function db_response(er, resp, body) {
|
|
108
|
+
clearTimeout(timeout_id);
|
|
109
|
+
|
|
110
|
+
if(er)
|
|
111
|
+
return self.die(er);
|
|
112
|
+
|
|
113
|
+
var db;
|
|
114
|
+
try {
|
|
115
|
+
db = JSON.parse(body)
|
|
116
|
+
} catch(json_er) {
|
|
117
|
+
return self.emit('error', json_er)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if(!db.db_name || !db.instance_start_time)
|
|
121
|
+
return self.emit('error', new Error('Bad DB response: ' + body));
|
|
122
|
+
|
|
123
|
+
self.original_db_seq = db.update_seq
|
|
124
|
+
self.log.debug('Confirmed db: ' + self.db_safe);
|
|
125
|
+
self.emit('confirm', db);
|
|
126
|
+
|
|
127
|
+
if(self.since == 'now') {
|
|
128
|
+
self.log.debug('Query since "now" is the same as query since -1')
|
|
129
|
+
self.since = -1
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if(self.since < 0) {
|
|
133
|
+
self.log.debug('Query since '+self.since+' will start at ' + (db.update_seq + self.since + 1))
|
|
134
|
+
self.since = db.update_seq + self.since + 1
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// If the next change would come after the current update_seq, just fake a catchup event now.
|
|
138
|
+
if(self.original_db_seq == self.since) {
|
|
139
|
+
self.caught_up = true
|
|
140
|
+
self.emit('catchup', db.update_seq)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return self.query();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
Feed.prototype.query = function query_feed() {
|
|
148
|
+
var self = this;
|
|
149
|
+
|
|
150
|
+
var query_params = JSON.parse(JSON.stringify(self.query_params));
|
|
151
|
+
|
|
152
|
+
FEED_PARAMETERS.forEach(function(key) {
|
|
153
|
+
if(key in self)
|
|
154
|
+
query_params[key] = self[key];
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
if(typeof query_params.filter !== 'string')
|
|
158
|
+
delete query_params.filter;
|
|
159
|
+
|
|
160
|
+
if(typeof self.filter === 'function' && !query_params.include_docs) {
|
|
161
|
+
self.log.debug('Enabling include_docs for client-side filter');
|
|
162
|
+
query_params.include_docs = true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Limit the response size for longpoll.
|
|
166
|
+
var poll_size = 100;
|
|
167
|
+
if(query_params.feed == 'longpoll' && (!query_params.limit || query_params.limit > poll_size))
|
|
168
|
+
query_params.limit = poll_size;
|
|
169
|
+
|
|
170
|
+
var feed_url = self.db + '/_changes?' + querystring.stringify(query_params);
|
|
171
|
+
|
|
172
|
+
self.headers.accept = self.headers.accept || 'application/json';
|
|
173
|
+
var req = { method : 'GET'
|
|
174
|
+
, uri : feed_url
|
|
175
|
+
, headers: self.headers
|
|
176
|
+
, encoding: 'utf-8'
|
|
177
|
+
, onResponse: on_feed_response
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
req.changes_query = query_params;
|
|
181
|
+
Object.keys(self.request).forEach(function(key) {
|
|
182
|
+
req[key] = self.request[key];
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
var now = new Date
|
|
186
|
+
, feed_ts = lib.JDUP(now)
|
|
187
|
+
, feed_id = process.env.follow_debug ? feed_ts.match(/\.(\d\d\d)Z$/)[1] : feed_ts
|
|
188
|
+
|
|
189
|
+
self.log.debug('Feed query ' + feed_id + ': ' + lib.scrub_creds(feed_url))
|
|
190
|
+
var feed_request = request(req)
|
|
191
|
+
feed_request.on('response', function() {
|
|
192
|
+
self.log.debug('Remove feed from agent pool: ' + feed_id)
|
|
193
|
+
feed_request.req.socket.emit('agentRemove')
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// The response headers must arrive within one heartbeat.
|
|
197
|
+
var response_timer = setTimeout(response_timed_out, self.heartbeat)
|
|
198
|
+
, timed_out = false
|
|
199
|
+
|
|
200
|
+
return self.emit('query', feed_request)
|
|
201
|
+
|
|
202
|
+
function response_timed_out() {
|
|
203
|
+
self.log.debug('Feed response timed out: ' + feed_id)
|
|
204
|
+
timed_out = true
|
|
205
|
+
return self.retry()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function on_feed_response(er, resp, body) {
|
|
209
|
+
clearTimeout(response_timer)
|
|
210
|
+
|
|
211
|
+
if((resp !== undefined && resp.body) || body)
|
|
212
|
+
return self.die(new Error('Cannot handle a body in the feed response: ' + lib.JS(resp.body || body)))
|
|
213
|
+
|
|
214
|
+
if(timed_out) {
|
|
215
|
+
self.log.debug('Ignoring late response: ' + feed_id);
|
|
216
|
+
return destroy_response(resp);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if(er) {
|
|
220
|
+
self.log.debug('Request error ' + feed_id + ': ' + er.stack);
|
|
221
|
+
destroy_response(resp);
|
|
222
|
+
return self.retry();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if(resp.statusCode !== 200) {
|
|
226
|
+
self.log.debug('Bad changes response ' + feed_id + ': ' + resp.statusCode);
|
|
227
|
+
destroy_response(resp);
|
|
228
|
+
return self.retry();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
self.log.debug('Good response: ' + feed_id);
|
|
232
|
+
self.retry_delay = INITIAL_RETRY_DELAY;
|
|
233
|
+
|
|
234
|
+
self.emit('response', resp);
|
|
235
|
+
|
|
236
|
+
var changes_stream = new Changes
|
|
237
|
+
changes_stream.log = lib.log4js.getLogger('stream ' + self.db)
|
|
238
|
+
changes_stream.log.setLevel(self.log.level.levelStr)
|
|
239
|
+
changes_stream.feed = self.feed
|
|
240
|
+
feed_request.pipe(changes_stream)
|
|
241
|
+
|
|
242
|
+
changes_stream.created_at = now
|
|
243
|
+
changes_stream.id = function() { return feed_id }
|
|
244
|
+
return self.prep(changes_stream)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
Feed.prototype.prep = function prep_request(changes_stream) {
|
|
249
|
+
var self = this;
|
|
250
|
+
|
|
251
|
+
var now = new Date;
|
|
252
|
+
self.pending.request = changes_stream;
|
|
253
|
+
self.pending.activity_at = now;
|
|
254
|
+
self.pending.wait_timer = null;
|
|
255
|
+
|
|
256
|
+
// The inactivity timer is for time between *changes*, or time between the
|
|
257
|
+
// initial connection and the first change. Therefore it goes here.
|
|
258
|
+
self.change_at = now;
|
|
259
|
+
if(self.inactivity_ms) {
|
|
260
|
+
clearTimeout(self.inactivity_timer);
|
|
261
|
+
self.inactivity_timer = setTimeout(function() { self.on_inactivity() }, self.inactivity_ms);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
changes_stream.on('heartbeat', handler_for('heartbeat'))
|
|
265
|
+
changes_stream.on('error', handler_for('error'))
|
|
266
|
+
changes_stream.on('data', handler_for('data'))
|
|
267
|
+
changes_stream.on('end', handler_for('end'))
|
|
268
|
+
|
|
269
|
+
return self.wait();
|
|
270
|
+
|
|
271
|
+
function handler_for(ev) {
|
|
272
|
+
var name = 'on_couch_' + ev;
|
|
273
|
+
var inner_handler = self[name];
|
|
274
|
+
|
|
275
|
+
return handle_confirmed_req_event;
|
|
276
|
+
function handle_confirmed_req_event() {
|
|
277
|
+
if(self.pending.request === changes_stream)
|
|
278
|
+
return inner_handler.apply(self, arguments);
|
|
279
|
+
|
|
280
|
+
if(!changes_stream.created_at)
|
|
281
|
+
return self.die(new Error("Received data from unknown request")); // Pretty sure this is impossible.
|
|
282
|
+
|
|
283
|
+
var s_to_now = (new Date() - changes_stream.created_at) / 1000;
|
|
284
|
+
var s_to_req = '[no req]';
|
|
285
|
+
if(self.pending.request)
|
|
286
|
+
s_to_req = (self.pending.request.created_at - changes_stream.created_at) / 1000;
|
|
287
|
+
|
|
288
|
+
var msg = ': ' + changes_stream.id() + ' to_req=' + s_to_req + 's, to_now=' + s_to_now + 's';
|
|
289
|
+
|
|
290
|
+
if(ev == 'end' || ev == 'data' || ev == 'heartbeat') {
|
|
291
|
+
self.log.debug('Old "' + ev + '": ' + changes_stream.id())
|
|
292
|
+
return destroy_req(changes_stream)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
self.log.warn('Old "'+ev+'"' + msg);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
Feed.prototype.wait = function wait_for_event() {
|
|
301
|
+
var self = this;
|
|
302
|
+
self.emit('wait');
|
|
303
|
+
|
|
304
|
+
if(self.pending.wait_timer)
|
|
305
|
+
return self.die(new Error('wait() called but there is already a wait_timer: ' + self.pending.wait_timer));
|
|
306
|
+
|
|
307
|
+
var timeout_ms = self.heartbeat * HEARTBEAT_TIMEOUT_COEFFICIENT;
|
|
308
|
+
var req_id = self.pending.request && self.pending.request.id()
|
|
309
|
+
var msg = 'Req ' + req_id + ' timeout=' + timeout_ms;
|
|
310
|
+
if(self.inactivity_ms)
|
|
311
|
+
msg += ', inactivity=' + self.inactivity_ms;
|
|
312
|
+
msg += ': ' + self.db_safe;
|
|
313
|
+
|
|
314
|
+
self.log.debug(msg);
|
|
315
|
+
self.pending.wait_timer = setTimeout(function() { self.on_timeout() }, timeout_ms);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
Feed.prototype.got_activity = function() {
|
|
319
|
+
var self = this
|
|
320
|
+
|
|
321
|
+
if(! self.pending.wait_timer)
|
|
322
|
+
return self.die(new Error('Cannot find wait timer'))
|
|
323
|
+
|
|
324
|
+
clearTimeout(self.pending.wait_timer)
|
|
325
|
+
self.pending.wait_timer = null
|
|
326
|
+
self.pending.activity_at = new Date
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
Feed.prototype.on_couch_heartbeat = function on_couch_heartbeat() {
|
|
330
|
+
var self = this
|
|
331
|
+
|
|
332
|
+
self.got_activity()
|
|
333
|
+
if(self.dead)
|
|
334
|
+
return self.log.debug('Skip heartbeat processing for dead feed')
|
|
335
|
+
|
|
336
|
+
self.emit('heartbeat')
|
|
337
|
+
|
|
338
|
+
if(self.dead)
|
|
339
|
+
return self.log.debug('No wait: heartbeat listener stopped this feed')
|
|
340
|
+
self.wait()
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
Feed.prototype.on_couch_data = function on_couch_data(change) {
|
|
344
|
+
var self = this;
|
|
345
|
+
self.log.debug('Data from ' + self.pending.request.id());
|
|
346
|
+
|
|
347
|
+
self.got_activity()
|
|
348
|
+
if(self.dead)
|
|
349
|
+
return self.log.debug('Skip data processing for dead feed')
|
|
350
|
+
|
|
351
|
+
// The changes stream guarantees that this data is valid JSON.
|
|
352
|
+
change = JSON.parse(change)
|
|
353
|
+
|
|
354
|
+
//self.log.debug('Object:\n' + util.inspect(change));
|
|
355
|
+
if('last_seq' in change) {
|
|
356
|
+
self.log.warn('Stopping upon receiving a final message: ' + JSON.stringify(change))
|
|
357
|
+
var del_er = new Error('Database deleted after change: ' + change.last_seq)
|
|
358
|
+
del_er.deleted = true
|
|
359
|
+
del_er.last_seq = change.last_seq
|
|
360
|
+
return self.die(del_er)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if(!change.seq)
|
|
364
|
+
return self.die(new Error('Change has no .seq field: ' + JSON.stringify(change)))
|
|
365
|
+
|
|
366
|
+
self.on_change(change)
|
|
367
|
+
|
|
368
|
+
// on_change() might work its way all the way to a "change" event, and the listener
|
|
369
|
+
// might call .stop(), which means among other things that no more events are desired.
|
|
370
|
+
// The die() code sets a self.dead flag to indicate this.
|
|
371
|
+
if(self.dead)
|
|
372
|
+
return self.log.debug('No wait: change listener stopped this feed')
|
|
373
|
+
self.wait()
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
Feed.prototype.on_timeout = function on_timeout() {
|
|
377
|
+
var self = this;
|
|
378
|
+
self.log.debug('Timeout')
|
|
379
|
+
|
|
380
|
+
var now = new Date;
|
|
381
|
+
var elapsed_ms = now - self.pending.activity_at;
|
|
382
|
+
|
|
383
|
+
self.emit('timeout', {elapsed_ms:elapsed_ms, heartbeat:self.heartbeat, id:self.pending.request.id()});
|
|
384
|
+
|
|
385
|
+
/*
|
|
386
|
+
var msg = ' for timeout after ' + elapsed_ms + 'ms; heartbeat=' + self.heartbeat;
|
|
387
|
+
if(!self.pending.request.id)
|
|
388
|
+
self.log.warn('Closing req (no id) ' + msg + ' req=' + util.inspect(self.pending.request));
|
|
389
|
+
else
|
|
390
|
+
self.log.warn('Closing req ' + self.pending.request.id() + msg);
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
destroy_req(self.pending.request);
|
|
394
|
+
self.retry()
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
Feed.prototype.retry = function retry() {
|
|
398
|
+
var self = this;
|
|
399
|
+
|
|
400
|
+
clearTimeout(self.pending.wait_timer);
|
|
401
|
+
self.pending.wait_timer = null;
|
|
402
|
+
|
|
403
|
+
self.log.debug('Retry since=' + self.since + ' after ' + self.retry_delay + 'ms ')
|
|
404
|
+
self.emit('retry', {since:self.since, after:self.retry_delay, db:self.db_safe});
|
|
405
|
+
|
|
406
|
+
self.retry_timer = setTimeout(function() { self.query() }, self.retry_delay);
|
|
407
|
+
|
|
408
|
+
var max_retry_ms = self.max_retry_seconds * 1000;
|
|
409
|
+
self.retry_delay *= 2;
|
|
410
|
+
if(self.retry_delay > max_retry_ms)
|
|
411
|
+
self.retry_delay = max_retry_ms;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
Feed.prototype.on_couch_end = function on_couch_end() {
|
|
415
|
+
var self = this;
|
|
416
|
+
|
|
417
|
+
self.log.debug('Changes feed ended ' + self.pending.request.id());
|
|
418
|
+
self.pending.request = null;
|
|
419
|
+
return self.retry();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
Feed.prototype.on_couch_error = function on_couch_error(er) {
|
|
423
|
+
var self = this;
|
|
424
|
+
|
|
425
|
+
self.log.debug('Changes query eror: ' + lib.JS(er.stack));
|
|
426
|
+
return self.retry();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
Feed.prototype.stop = function(val) {
|
|
430
|
+
var self = this
|
|
431
|
+
self.log.debug('Stop')
|
|
432
|
+
|
|
433
|
+
// Die with no errors.
|
|
434
|
+
self.die()
|
|
435
|
+
self.emit('stop', val);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
Feed.prototype.die = function(er) {
|
|
439
|
+
var self = this;
|
|
440
|
+
|
|
441
|
+
if(er)
|
|
442
|
+
self.log.fatal('Fatal error: ' + er.stack);
|
|
443
|
+
|
|
444
|
+
// Warn code executing later that death has occured.
|
|
445
|
+
self.dead = true
|
|
446
|
+
|
|
447
|
+
clearTimeout(self.retry_timer)
|
|
448
|
+
clearTimeout(self.inactivity_timer)
|
|
449
|
+
clearTimeout(self.pending.wait_timer)
|
|
450
|
+
|
|
451
|
+
self.inactivity_timer = null
|
|
452
|
+
self.pending.wait_timer = null
|
|
453
|
+
|
|
454
|
+
var req = self.pending.request;
|
|
455
|
+
self.pending.request = null;
|
|
456
|
+
if(req) {
|
|
457
|
+
self.log.debug('Destroying req ' + req.id());
|
|
458
|
+
destroy_req(req);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if(er)
|
|
462
|
+
self.emit('error', er);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
Feed.prototype.on_change = function on_change(change) {
|
|
466
|
+
var self = this;
|
|
467
|
+
|
|
468
|
+
if(!change.seq)
|
|
469
|
+
return self.die(new Error('No seq value in change: ' + lib.JS(change)));
|
|
470
|
+
|
|
471
|
+
if(change.seq <= self.since) {
|
|
472
|
+
self.log.debug('Bad seq value ' + change.seq + ' since=' + self.since);
|
|
473
|
+
return destroy_req(self.pending.request);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if(!self.caught_up && change.seq >= self.original_db_seq) {
|
|
477
|
+
self.caught_up = true
|
|
478
|
+
self.emit('catchup', change.seq)
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if(typeof self.filter !== 'function')
|
|
482
|
+
return self.on_good_change(change);
|
|
483
|
+
|
|
484
|
+
if(!change.doc)
|
|
485
|
+
return self.die(new Error('Internal filter needs .doc in change ' + change.seq));
|
|
486
|
+
|
|
487
|
+
// Don't let the filter mutate the real data.
|
|
488
|
+
var doc = lib.JDUP(change.doc);
|
|
489
|
+
var req = lib.JDUP({'query': self.pending.request.changes_query});
|
|
490
|
+
|
|
491
|
+
var result = false;
|
|
492
|
+
try {
|
|
493
|
+
result = self.filter.apply(null, [doc, req]);
|
|
494
|
+
} catch (er) {
|
|
495
|
+
self.log.debug('Filter error', er);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
result = (result && true) || false;
|
|
499
|
+
if(result) {
|
|
500
|
+
self.log.debug('Builtin filter PASS for change: ' + change.seq);
|
|
501
|
+
return self.on_good_change(change);
|
|
502
|
+
} else
|
|
503
|
+
self.log.debug('Builtin filter FAIL for change: ' + change.seq);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
Feed.prototype.on_good_change = function on_good_change(change) {
|
|
507
|
+
var self = this;
|
|
508
|
+
|
|
509
|
+
if(self.inactivity_ms && !self.inactivity_timer)
|
|
510
|
+
return self.die(new Error('Cannot find inactivity timer during change'));
|
|
511
|
+
|
|
512
|
+
clearTimeout(self.inactivity_timer);
|
|
513
|
+
self.inactivity_timer = null;
|
|
514
|
+
if(self.inactivity_ms)
|
|
515
|
+
self.inactivity_timer = setTimeout(function() { self.on_inactivity() }, self.inactivity_ms);
|
|
516
|
+
|
|
517
|
+
self.change_at = new Date;
|
|
518
|
+
self.since = change.seq;
|
|
519
|
+
self.emit('change', change);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
Feed.prototype.on_inactivity = function on_inactivity() {
|
|
523
|
+
var self = this;
|
|
524
|
+
var now = new Date;
|
|
525
|
+
var elapsed_ms = now - self.change_at;
|
|
526
|
+
var elapsed_s = elapsed_ms / 1000;
|
|
527
|
+
|
|
528
|
+
return self.die(new Error('Req ' + self.pending.request.id() + ' made no changes for ' + elapsed_s + 's'));
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
module.exports = { "Feed" : Feed
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
/*
|
|
536
|
+
* Utilities
|
|
537
|
+
*/
|
|
538
|
+
|
|
539
|
+
function destroy_req(req) {
|
|
540
|
+
if(req)
|
|
541
|
+
destroy_response(req.response)
|
|
542
|
+
|
|
543
|
+
if(req && typeof req.destroy == 'function')
|
|
544
|
+
req.destroy()
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function destroy_response(response) {
|
|
548
|
+
if(!response)
|
|
549
|
+
return;
|
|
550
|
+
|
|
551
|
+
if(typeof response.abort === 'function')
|
|
552
|
+
response.abort();
|
|
553
|
+
|
|
554
|
+
if(response.connection)
|
|
555
|
+
response.connection.destroy();
|
|
556
|
+
}
|