Skip to main content

subscribe

Since 1.6

Subscribes to changes against a specified root and requests that they be sent to the client via its connection. The updates will continue to be sent while the connection is open. If the connection is closed, the subscription is implicitly removed.

This makes the most sense in an application connecting via the socket interface, but you may also subscribe via the command line tool if you're interested in observing the changes for yourself:

$ watchman -j --server-encoding=json -p <<-EOT
["subscribe", "/path/to/root", "mysubscriptionname", {
"expression": ["allof",
["type", "f"],
["not", "empty"],
["suffix", "php"]
],
"fields": ["name"]
}]
EOT

The example above registers a subscription against the specified root with the name mysubscriptionname.

The response to a subscribe command looks like this:

{
"version": "1.6",
"subscribe": "mysubscriptionname"
}

When the subscription is first established, the expression term is evaluated and if any files match, a subscription notification packet is generated and sent, unilaterally to the client.

Then, each time a change is observed, and after the settle period has passed, the expression is evaluated again. If any files are matched, the server will unilaterally send the query results to the client with a packet that looks like this:

{
"version": "1.6",
"clock": "c:1234:123",
"files": ["one.php"],
"root": "/path/being/watched",
"subscription": "mysubscriptionname"
}

The subscribe command object allows the client to specify a since parameter; if present in the command, the initial set of subscription results will only include files that changed since the specified clockspec, equivalent to using the query command with the since generator.

["subscribe", "/path/to/root", "myname", {
"since": "c:1234:123",
"expression": ["not", "empty"],
"fields": ["name"]
}]

The suggested mode of operation is for the client process to maintain its own local copy of the last "clock" value and use that to establish the subscription when it first connects.

Filesystem Settling

Prior to watchman version 3.2, the settling behavior was to hold subscription notifications until the kernel notification stream was complete.

Starting in watchman version 3.2, after the notification stream is complete, if the root appears to be a version control directory, subscription notifications will be held until an outstanding version control operation is complete (at the time of writing, this is based on the presence of either .hg/wlock or .git/index.lock). This behavior matches triggers and helps to avoid performing transient work in response to files changing, for example, during a rebase operation.

In some circumstances it is desirable for a client to observe the creation of the control files at the start of a version control operation. You may specify that you want this behavior by passing the defer_vcs flag to your subscription command invocation:

$ watchman -j -p <<-EOT
["subscribe", "/path/to/root", "mysubscriptionname", {
"expression": ["allof",
["type", "f"],
["not", "empty"],
["suffix", "php"]
],
"defer_vcs": false,
"fields": ["name"]
}]
EOT

Advanced Settling

Since 4.4

In more complex integrations it is desirable to be able to have a watchman aware application signal the beginning and end of some work that will generate a lot of change notifications. For example, Mercurial or Git could communicate with watchman before and after updating the working copy.

Some applications will want to know that the update is in progress and continue to process notifications. Others may want to defer processing the notifications until the update completes, and some may wish to drop any notifications produced while the update was in progress.

Watchman subscriptions provide the mechanism for each of these use cases and expose it via two new fields in the subscription object; defer and drop are described below.

It can be difficult to mix defer and drop with multiple overlapping states in the context of a given subscription stream as there is a single cursor to track the subscription position.

If your application uses multiple overlapping states and wants to defer some results and drop others, it is recommended that you use drop for all of the states and then issues queries with since terms bounded by the clock fields from the subscription state PDUs to ensure that it observes all of the results of interest.

defer

["subscribe", "/path/to/root", "mysubscriptionname", {
"defer": ["mystatename"],
"fields": ["name"]
}]

The defer field specifies a list of state names for which the subscriber wishes to defer the notification stream. When a watchman client signals that a state has been entered via the state-enter command, if the state name matches any in the defer list then the subscription will emit a unilateral subscription PDU like this:

{
"subscription": "mysubscriptionname",
"root": "/path/to/root",
"state-enter": "mystatename",
"clock": "<clock>",
"metadata": <metadata from the state-enter command>
}

Watchman will then defer sending any subscription PDUs with files payloads until the state is vacated either by a state-leave command or by the client that entered the state disconnecting from the watchman service.

Once the state is vacated, watchman will emit a unilateral subscription PDU like this:

{
"subscription": "mysubscriptionname",
"root": "/path/to/root",
"state-leave": "mystatename",
"clock": "<clock>",
"metadata": <metadata from the exit-state command>
}

The subscription stream will then be re-enabled and notifications received since the corresponding state-enter will be delivered to clients.

drop

["subscribe", "/path/to/root", "mysubscriptionname", {
"drop": ["mystatename"],
"fields": ["name"]
}]

The drop field specifies a list of state names for which the subscriber wishes to discard the notification stream. It works very much like defer as described above, but when a state is vacated, the pending notification stream is fast-forwarded to the clock of the state-leave command, effectively suppressing any notifications that were generated between the state-enter and the state-leave commands.

Source Control Aware Subscriptions

Since 4.9

Read more about these here