Summary:
Fixes T7130. Fixes T7041. Fixes T7012.
Major change here is partitioning clients. In the Phacility cluster, being able to get a huge pile of instances on a single server -- without needing to run a process per instance -- is desirable.
To accomplish this, just bucket clients by the path they connect with. This will let us set client URIs to `/instancename/` and then route connections to a small set of servers. This degrades cleanly in the common case and has no effect on installs which don't do instancing.
Also fix two unrelated issues:
- Fix the timeouts, which were incorrectly initializing in `open()` (which is called during reconnect, causing them to reset every time). Instead, initialize in the constructor. Cap timeout at 5 minutes.
- Probably fix subscriptions, which were using a property with an object definition. Since this is by-ref, all concrete instances of the object share the same property, so all users would be subscribed to everything. Probably.
Test Plan:
- Hit notification status page, saw version bump and instance/path name.
- Saw instance/path name in client and server logs.
- Stopped server, saw reconnects after 2, 4, 16, ... seconds.
- Sent test notification; received test notification.
- Didn't explicitly test the subscription thing but it should be obvious by looking at `/notification/status/` shortly after a push.
Reviewers: joshuaspence, btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7041, T7012, T7130
Differential Revision: https://secure.phabricator.com/D11769
Summary: Ref T7124. The local version of `this` in the handler of 'end' was incremented rather than the global one.
Test Plan: Sending test notifications did not increment the `messages.in` value before this patch even if it should have. With the patch sending test notifications does increment `messages.in`.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: Korvin, epriestley
Maniphest Tasks: T7124
Differential Revision: https://secure.phabricator.com/D11648
Summary: Ref T7126. Dictionaries do not have a `length` property unlike arrays resulting in the `getActiveListenerCount()` function returning undefined results. Using the `length` property on the array of keys will work.
Test Plan: Using `wscat` to generate multiple connections to the server, establish new ones and close others while keeping an eye on the displayed `clients.active` value.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Maniphest Tasks: T7126
Differential Revision: https://secure.phabricator.com/D11647
Summary: Ref T7110. Listeners are now removed when clients close the connection to avoid stacking a never ending number of unused listeners.
Test Plan: Using `wscat` to connect to the Aphlict server; when closing the connection a 'Diconnected.' will appear in the logs and the number of active listeners is decreased by one.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Maniphest Tasks: T7110
Differential Revision: https://secure.phabricator.com/D11634
Summary: Add the logger as soon as possible so that the log file will contain errors if the `ws` module cannot be loaded.
Test Plan: Ran `./bin/aphlict debug` without having the `ws` module installed. Saw errors in the logs.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11457
Summary:
In particular, this changes the behavior of NodeJS in the following ways:
- Any attempt to get or modify the global object will result in an error.
- `null` values of `this` will no longer be evaluated to the global object and primitive values of this will not be converted to wrapper objects.
- Writing or deleting properties which have there writeable or configurable attributes set to false will now throw an error instead of failing silently.
- Adding a property to an object whose extensible attribute is false will also throw an error now.
- A functions arguments are not writeable so attempting to change them will now throw an error `arguments = [...]`.
- `with(){}` statements are gone.
- Use of `eval` is effectively banned.
- `eval` and `arguments` are not allowed as variable or function identifiers in any scope.
- The identifiers `implements`, `interface`, `let`, `package`, `private`, `protected`, `public`, `static` and `yield` are all now reserved for future use (roll on ES6).
Test Plan: Verified that Aphlict was still functional.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11430
Summary:
This was broken in D11383. Basically, I had the `ws` module installed globally whilst testing, but the changes made do not work if the `ws` module is installed locally (i.e. in the `./support/aphlict/server/node_modules` directory). After poking around, it seems that this is due to the sandboxing that is done by `JX.require`.
A quick fix is to just //not// use `JX.require`, although you may have a better idea?
The error that is occurring is as follows:
```
<<< UNCAUGHT EXCEPTION! >>>
Error: Cannot find module 'ws'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at extra.require (/usr/src/phabricator/webroot/rsrc/externals/javelin/core/init_node.js:48:16)
at /usr/src/phabricator/support/aphlict/server/lib/AphlictClientServer.js:10:17
at Script.(anonymous function) [as runInNewContext] (vm.js:41:22)
at Object.JX.require (/usr/src/phabricator/webroot/rsrc/externals/javelin/core/init_node.js:58:6)
at Object.<anonymous> (/usr/src/phabricator/support/aphlict/server/aphlict_server.js:102:4)
at Module._compile (module.js:456:26)
>>> Server exited!
```
Test Plan: Now able to start the Aphlict server.
Reviewers: joshuaspence
Reviewed By: joshuaspence
Subscribers: Korvin, epriestley
Maniphest Tasks: T6987
Differential Revision: https://secure.phabricator.com/D11425
Summary: By calling `process.exit(1)` we are forcing the Node.js process to exit prematurely. Specifically, the process is terminated before the error is written to the log file. This can be verified by inspecting the value of `debug._logs[0]._writableState.writing` immediately before the process is terminated.
Test Plan: Ran `./bin/aphlict debug` without the `ws` module being installed. Verified that `<<< UNCAUGHT EXCEPTION! >>>` was echoed to the console as well as the log file. Also verified that the exit status was non-zero.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11426
Summary: Tidy the Aphlict server by splitting the functionality into two main modules, `AphlictClientServer` and `AphlictAdminServer. There is still further tidying that could be done here, but I feel that this puts us in a much better place.
Test Plan: Sent notifications via `/notification/status/`.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11383
Summary: Currently, the Aphlict server created the log file (if it doesn't exist) but then immediately fails with "Unable to open logfile". It seems that we don't set the permissions correctly.
Test Plan: Deleted log file and was able to start the Aphlict server.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11351
Summary:
Yeahhhhhhhh....
- Open a "stream", not a "steam".
- Make error easier for users to understand.
- Write to the log in debug mode so the issue is more apparent.
Test Plan:
- Started server with bad permissions, got usable error message.
- Started server with good permissions, got logfile.
Reviewers: joshuaspence, btrahan
Reviewed By: btrahan
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11339
Summary: If you are running the Aphlict server behind a reverse proxy (such as `nginx`) then there's no need to bind to `0.0.0.0`. Add a `--client-host` flag to `aphlict_server.js` to allow binding to a different hostname. Also changed the other flags for consistency and clarity.
Test Plan: Started, stopped and debug the Aphlict server.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11288
Summary: Fixes T6910. This advice is bad, doesn't work, and was based on me havng an outdated or incorrect understanding of Node and npm.
Test Plan: Read documentation.
Reviewers: richardvanvelzen, btrahan, chad, joshuaspence
Reviewed By: chad, joshuaspence
Subscribers: epriestley
Maniphest Tasks: T6910
Differential Revision: https://secure.phabricator.com/D11285
Summary:
Fixes T6559. No more flash, use Websockets. This is less aggressive than the earlier version, and retains more server logic.
- Support "wss".
- Make the client work.
- Remove "notification.user" entirely.
- Seems ok?
Test Plan:
In Safari, Firefox and Chrome, saw the browsers connect. Made a bunch of comments/updates and saw notifications.
Notable holes in the test plan:
- Haven't tested "wss" yet. I'll do this on secure.
- Notifications are //too fast// now, locally. I get them after I hit submit but before the page reloads.
- There are probably some other rough edges, this is a fairly big patch.
Reviewers: joshuaspence, btrahan
Reviewed By: joshuaspence, btrahan
Subscribers: fabe, btrahan, epriestley
Maniphest Tasks: T6713, T6559
Differential Revision: https://secure.phabricator.com/D11143
Summary: We don't need to handle any request data for the `/status/` route, so we can simplify this code slightly.
Test Plan:
```lang=bash
> curl http://127.0.0.1:22281/status/
{"uptime":2543,"clients.active":0,"clients.total":0,"messages.in":0,"messages.out":0,"log":"/var/log/aphlict.log","version":6}
```
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11145
Summary: Basically, don't assign expressions to a variable if the variable is unused.
Test Plan: `arc lint`
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D11072
Summary: Ref T5651. Only throw a HTTP 400 if the data is invalid (i.e. the request is bad). If something bad happens when trying to transmit the notification, throw a HTTP 500 instead.
Test Plan: Eye-ball it.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Maniphest Tasks: T5651
Differential Revision: https://secure.phabricator.com/D9968
Summary: Ref T5651. Currently, the Aphlict server returns either `200 OKAY` or `400 Bad Request`. We could return more specific errors in some cases and this may assist with debugging.
Test Plan:
Sent myself a test notification at `/notification/status/` and saw the Aphlict server process the request (running in debug mode). Also poked around with `curl`:
```
> curl http://localhost:22281/
405 Method Not Allowed
> curl http://localhost:22281/ -d ""
400 Bad Request
> curl http://localhost:22281/foobar/
404 Not Found
```
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Maniphest Tasks: T5651
Differential Revision: https://secure.phabricator.com/D9967
Summary: Fixes T5651. Sometime we'll send an object to the notification server for `subscribers`, which it will choke on. Use `array_values()` to make sure we're sending an array.
Test Plan: With `(object)` instead, got a consistent error ("no .filter method on object"). With `array_values()`, no error.
Reviewers: joshuaspence
Reviewed By: joshuaspence
Subscribers: epriestley
Maniphest Tasks: T5651
Differential Revision: https://secure.phabricator.com/D9963
Summary: Various fixes as suggested by JSHint.
Test Plan: Eye-balled it.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9783
Summary: Ref T5365. Surface disconnects in the UI.
Test Plan:
- Connected, then killed the server.
- Saw disconnected event and appropriate update in the UI.
{F169605}
Reviewers: joshuaspence
Reviewed By: joshuaspence
Subscribers: epriestley
Maniphest Tasks: T5365
Differential Revision: https://secure.phabricator.com/D9706
Summary:
Fixes T5373. Ref T5281. Several changes:
- The `marshallExceptions` thing is useful if JS throws an exception when invoked from Flash, so set it. The resulting exceptions are a little odd (not escaped correctly, e.g.) but way better than nothing.
- Put connection status in the notification menu.
- When the connection fails, try to provide contextual help where we can.
Test Plan: {F169493}
Reviewers: chad, joshuaspence
Reviewed By: joshuaspence
Subscribers: epriestley
Maniphest Tasks: T5281, T5373
Differential Revision: https://secure.phabricator.com/D9700
Summary:
Ref T5373. The control flow between `aphlict-listener` and `JX.Aphlict` is pretty weird right now, where the listener (which is the highest-level component) has intimate knowledge of how to put the SWF on the page.
Instead:
- Make `JX.Aphlict` a real singleton.
- Instantiate it sooner.
- Have it handle the flash setup handshake.
Test Plan: Loaded page in debug mode, saw normal flow take place.
Reviewers: joshuaspence
Reviewed By: joshuaspence
Subscribers: epriestley
Maniphest Tasks: T5373
Differential Revision: https://secure.phabricator.com/D9699
Summary:
Ref T5373. This seems to work pretty much correctly.
Also stop popping bubbles and just use the log, since users find the bubbles confusing/not useful and they're not great for developers either.
Future diffs will expose more user-facing stuff.
Test Plan: Added `throw` to AphlictClient.as, got a log in the parent window.
Reviewers: joshuaspence
Reviewed By: joshuaspence
Subscribers: epriestley
Maniphest Tasks: T5373
Differential Revision: https://secure.phabricator.com/D9698
Summary: Most scripts detect the relevant workflows automatically. Some scripts, however, use a hardcoded list of workflows.
Test Plan: Ran `./bin/aphlict`, `./bin/cache` and `./bin/phd`.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9564
Summary: The `_activeListenerCount` variable is overkill, we should be able to achieve the same result using `Object.keys(this._listeners).length`.
Test Plan:
Mucked around in a NodeJS shell.
```lang=js
> Object.keys({}).length
0
> Object.keys({foo: 'bar'}).length
1
> Object.keys({1: 'foo', 2: 'bar'}).length
2
```
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9554
Summary: As pointed out by @epriestley in D9458#62, this call to `debug.log` is missing an argument.
Test Plan: meh..
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D9485
Summary: Ref T5284. When an `AphlictClient` is closed, it will eventually be purged from the pool by the `AphlictMaster`. When this happens, also unsubscribe the purged client from all notifications, and send an `unsubscribe` command to the Aphlict server if possible.
Test Plan:
Verified the output of the Aphlict server (running in debug mode):
```
[Wed Jun 11 2014 23:21:31 GMT+0000 (UTC)] <FlashPolicy> Policy Request From ::ffff:192.168.1.1
[Wed Jun 11 2014 23:21:31 GMT+0000 (UTC)] <Listener/2> Connected from ::ffff:192.168.1.1
[Wed Jun 11 2014 23:21:31 GMT+0000 (UTC)] <Listener/2> Received data: {"command":"subscribe","data":["PHID-USER-cb5af6p4oepy5tlgqypi"]}
[Wed Jun 11 2014 23:21:31 GMT+0000 (UTC)] <Listener/2> Subscribed to: ["PHID-USER-cb5af6p4oepy5tlgqypi"]
[Wed Jun 11 2014 23:21:39 GMT+0000 (UTC)] <Listener/2> Received data: {"command":"subscribe","data":["PHID-TASK-l2dtbs5xrt2b7abgh5a6"]}
[Wed Jun 11 2014 23:21:39 GMT+0000 (UTC)] <Listener/2> Subscribed to: ["PHID-TASK-l2dtbs5xrt2b7abgh5a6"]
[Wed Jun 11 2014 23:21:57 GMT+0000 (UTC)] <Listener/2> Received data: {"command":"unsubscribe","data":["PHID-TASK-l2dtbs5xrt2b7abgh5a6"]}
[Wed Jun 11 2014 23:21:57 GMT+0000 (UTC)] <Listener/2> Unsubscribed from: ["PHID-TASK-l2dtbs5xrt2b7abgh5a6"]
```
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Maniphest Tasks: T5284
Differential Revision: https://secure.phabricator.com/D9492
Summary: Currently, the `AphlictClient` will only send its subscriptions to the `AphlictMaster` once. If the original `AphlictMaster` is closed and a new master is created, then client subscriptions will be lost.
Test Plan: Opened two separate tabs. Closed the "master" tab and noticed that the subscriptions were re-sent to the server.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9487
Summary: Ref T4324. Ref T5284. This adds server-side support for keeping track of a set of PHIDs that the Aphlict clients have subscribed to. Instead of broadcasting a notification to all clients (after which the clients can poll `/notification/individual` in order to determine whether or not they are interested in the notification), transmit notifications only to clients that have subscribed to a PHID that is relevant to the notification.
Test Plan:
I opened up two clients on the same host (incognito tabs in Chrome). Here is the output from the server:
```
> sudo ./bin/aphlict debug
Starting Aphlict server in foreground...
Launching server:
$ 'nodejs' '/usr/src/phabricator/src/applications/aphlict/management/../../../../support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost' --user='aphlict'
[Wed Jun 11 2014 19:10:27 GMT+0000 (UTC)] Started Server (PID 4546)
[Wed Jun 11 2014 19:10:36 GMT+0000 (UTC)] <FlashPolicy> Policy Request From ::ffff:192.168.1.1
[Wed Jun 11 2014 19:10:37 GMT+0000 (UTC)] <Listener/1> Connected from ::ffff:192.168.1.1
[Wed Jun 11 2014 19:10:37 GMT+0000 (UTC)] <Listener/1> Received data: {"command":"subscribe","data":["PHID-USER-cb5af6p4oepy5tlgqypi"]}
[Wed Jun 11 2014 19:10:37 GMT+0000 (UTC)] <Listener/1> Subscribed to: ["PHID-USER-cb5af6p4oepy5tlgqypi"]
[Wed Jun 11 2014 19:10:39 GMT+0000 (UTC)] <Listener/1> Received data: {"command":"subscribe","data":["PHID-USER-kfohe3ca5oe6ygykmioq"]}
[Wed Jun 11 2014 19:10:39 GMT+0000 (UTC)] <Listener/1> Subscribed to: ["PHID-USER-kfohe3ca5oe6ygykmioq"]
[Wed Jun 11 2014 19:10:42 GMT+0000 (UTC)] notification: {"key":"6023751084283587681","type":"notification","subscribers":["PHID-USER-cb5af6p4oepy5tlgqypi"]}
[Wed Jun 11 2014 19:10:42 GMT+0000 (UTC)] <Listener/1> Wrote Message
```
I verified (using the "Network" tab in Chrome) that an AJAX request to `/notification/individual/` was only made in the tab belonging to the user that triggered the test notification.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Maniphest Tasks: T5284, T4324
Differential Revision: https://secure.phabricator.com/D9458
Summary: Printing out `err` is less informative than `err.stack`, which has the message, type, //and// a trace.
Test Plan:
Faked an exception, then:
```
$ sudo ./bin/aphlict debug
Starting Aphlict server in foreground...
Launching server:
$ 'node' '/INSECURE/devtools/phabricator/src/applications/aphlict/management/../../../../support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost'
[Wed Jun 11 2014 10:20:39 GMT-0700 (PDT)]
<<< UNCAUGHT EXCEPTION! >>>
Error: Example Exception
at Object.<anonymous> (/INSECURE/devtools/phabricator/support/aphlict/server/aphlict_server.js:73:7)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3
>>> Server exited!
```
Reviewers: joshuaspence
Reviewed By: joshuaspence
Subscribers: epriestley
Differential Revision: https://secure.phabricator.com/D9481
Summary:
Currently, the Aphlict server will crash if invalid JSON data is `POST`ed to it. I have fixed this to, instead, return a 400. Also made some minor formatting changes.
Ref T4324. Ref T5284. Also, modify the data structure that is passed around (i.e. `POST`ed to the Aphlict server and broadcast to the Aphlict clients) to include the subscribers. Initially, I figured that we shouldn't expose this information to the clients... however, it is necessary for T4324 that the `AphlictMaster` is able to route a notification to the appropriate clients.
Test Plan:
Making the following `curl` request: `curl --data "{" http://localhost:22281/`.
**Before**
```
sudo ./bin/aphlict debug
Starting Aphlict server in foreground...
Launching server:
$ 'nodejs' '/usr/src/phabricator/src/applications/aphlict/management/../../../../support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost' --user='aphlict'
[Wed Jun 11 2014 17:07:51 GMT+0000 (UTC)] Started Server (PID 2033)
[Wed Jun 11 2014 17:07:55 GMT+0000 (UTC)]
<<< UNCAUGHT EXCEPTION! >>>
SyntaxError: Unexpected end of input
>>> Server exited!
```
**After**
(No output... the bad JSON is caught and a 400 is returned)
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Maniphest Tasks: T4324, T5284
Differential Revision: https://secure.phabricator.com/D9480
Summary: Currently, any error thrown when instantiating an `AphlictMaster` will be assumed to be due to the master already existing. This is a bit overzealous because the [[http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/LocalConnection.html#connect() | documentation]] specifically states than an `ArgumentError` will be throw if "the `LocalConnection` instance is already connected".
Test Plan: Inspected the log message.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9422
Summary: These methods shouldn't be overridden. Marking them as `final` will enforce this.
Test Plan: N/A
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9411
Summary:
Currently, it is a bit tricky to build the Aphlict client SWF from the ActionScript source. Provide a `./bin/aphlict build` workflow that simplifies this process.
Depends on D9226.
Test Plan:
Executed the workflow:
```
> ./bin/aphlict build
Done.
```
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9338
Summary: Fixes T5126. Provide `start`, `stop`, `restart`, `debug` and `status` workflows for `./bin/aphlict`. This makes it easier to manage Aphlict as if it were a service.
Test Plan:
```
> sudo ./bin/aphlict status
Aphlict is not running.
> sudo ./bin/aphlict stop
Aphlict is not running.
> sudo ./bin/aphlict start
Aphlict Server started.
> sudo ./bin/aphlict status
Aphlict (12880) is running.
> sudo ./bin/aphlict restart
Stopping Aphlict Server (12880)...
Aphlict Server (12880) exited normally.
Aphlict Server started.
> sudo ./bin/aphlict stop
Stopping Aphlict Server (12895)...
Aphlict Server (12895) exited normally.
> sudo ./bin/aphlict debug
Starting Aphlict server in foreground...
Launching server:
$ node '/usr/src/phabricator/src/applications/aphlict/management/../../../../support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost' --user='aphlict'
[Fri May 30 2014 09:56:14 GMT+0000 (UTC)] Started Server (PID 12911)
```
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: hach-que, epriestley, Korvin
Maniphest Tasks: T5126
Differential Revision: https://secure.phabricator.com/D9226
Summary:
Ref T4324. As well as sending the key for the notification, also publish the notification type and a list of subscribers to the Aphlict server.
The idea here is that the Aphlict server passes anything within the `data` key to the clients, whereas other keys (such as `subscribers`) will be used by the server to determine where the notifications should be routed.
Note that these changes don't do anything useful, but are a prerequisite for further work on T4324.
Test Plan:
Sent myself test notifications at `/notification/status/`. Also inspected the Aphlict server debug output:
```
> sudo ./bin/aphlict --foreground
Starting server in foreground, ignoring pidfile...
Launching server:
$ node '/usr/src/phabricator/support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost' --user='aphlict' --log='/var/log/aphlict.log'
[Thu Jun 05 2014 18:38:14 GMT+0000 (UTC)] Started Server (PID 15437)
[Thu Jun 05 2014 18:38:16 GMT+0000 (UTC)] <FlashPolicy> Policy Request From ::ffff:10.0.0.1
[Thu Jun 05 2014 18:38:16 GMT+0000 (UTC)] <Listener/1> Connected from ::ffff:10.0.0.1
[Thu Jun 05 2014 18:38:19 GMT+0000 (UTC)] notification: {"data":{"key":"6021516228036848559","type":"notification"},"subscribers":["PHID-USER-cb5af6p4oepy5tlgqypi"]}
[Thu Jun 05 2014 18:38:19 GMT+0000 (UTC)] <Listener/1> Wrote Message
```
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Maniphest Tasks: T4324
Differential Revision: https://secure.phabricator.com/D9396
Summary:
Ref T4324. Currently, notifications data is `POST`ed to the Aphlict server in the `application/x-www-form-urlencoded` format. This works fine for simple data but is problematic for nested data. For example:
```lang=php
array(
'data' => array(
'key' => '6021329908492455737',
'type' => 'PhabricatorNotificationAdHocFeedStory',
),
'subscribers' => array(
'PHID-USER-y7ofqm276ejs62yqghge',
),
);
```
Is encoded as `data%5Bkey%5D=6021329908492455737&data%5Btype%5D=PhabricatorNotificationAdHocFeedStory&subscribers%5B0%5D=PHID-USER-y7ofqm276ejs62yqghge`. This string is then (incorrectly) decoded by `querystring.parse` as:
```lang=javascript
> querystring.parse('data%5Bkey%5D=6021329908492455737&data%5Btype%5D=PhabricatorNotificationAdHocFeedStory&subscribers%5B0%5D=PHID-USER-y7ofqm276ejs62yqghge');
{ 'data[key]': '6021329908492455737',
'data[type]': 'PhabricatorNotificationAdHocFeedStory',
'subscribers[0]': 'PHID-USER-y7ofqm276ejs62yqghge' }
```
Test Plan: Sent test notifications from `/notification/status/` and verified that the notifications still worked.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Maniphest Tasks: T4324
Differential Revision: https://secure.phabricator.com/D9386
Summary: Ref T4324. Currently, if the `AphlictMaster` receives dodgy data from the Aphlict server (invalid JSON, for example) then a syntax error will be thrown and the `AphlictMaster` will die. Instead, catch errors and raise a notification.
Test Plan: {F163466}
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Maniphest Tasks: T4324
Differential Revision: https://secure.phabricator.com/D9380
Summary:
Strict mode is enabled by default, but it would be best to explicitly enable it... just in case.
Strict mode prints undefined property and function calls; also performs compile-time type checking on assignments and options supplied to method calls. See http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7a92.html
Test Plan: N/A
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9354
Summary: These settings don't seem to make any difference and are somewhat confusing.
Test Plan: Sent myself test notifications via `/notification/status`. Things seemed to work.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D9337
Summary:
Ref T4324. Currently, an Aphlict client (with a corresponding connection to the Aphlict Server) is created for every tab that a user has open. This significantly affects the scalability of Aphlict as a service. Instead, we can use `LocalConnection` instances to coordinate the communication of multiple Aphlict clients to the server.
Similar functionality existed prior to D2704, but was removed as the author was not able to get this functionality working as intended. It seems that the main issue with the initial attempt was the use of the `setTimeout` function, which seemed to be a blocking call which prevented messages from being received. I have instead used an event-based model using a `Timer` object.
Roughly this works as follows:
# The first instance will create an `AphlictClient` and an `AphlictMaster`. The `AphlictClient` will register itself with the `AphlictMaster` and will consequently be notified of incoming messages.
# The `AphlictClient` is then responsible for pinging the `AphlictMaster` at regular intervals. If the client does not ping the master in a given period of time, the master will assume that the client is dead and will remove the client from the pool.
# Similarly, the `AphlictMaster` is required to respond to pings with a "pong" response. The pong response lets the clients know that the `AphlictMaster` is still alive. If the clients do not receive a pong in a given period of time, then the clients will attempt to spawn a new master.
Test Plan: I have tested this on our Phabricator install with a few tabs opened and inspecting the console output. I will upload a screencast of my test results.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: epriestley, Korvin
Maniphest Tasks: T4324
Differential Revision: https://secure.phabricator.com/D9327