File: cmd.subscribe.markdown

package info (click to toggle)
watchman 4.9.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 9,992 kB
  • sloc: cpp: 27,459; python: 6,538; java: 3,404; php: 3,257; ansic: 2,803; javascript: 1,116; makefile: 671; ruby: 364; sh: 124; xml: 102; lisp: 4
file content (209 lines) | stat: -rw-r--r-- 6,763 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
---
pageid: cmd.subscribe
title: subscribe
layout: docs
section: Commands
permalink: docs/cmd/subscribe.html
---

*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:

```bash
$ 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:

```json
{
  "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:

```json
{
  "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.

```json
["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:

```bash
$ 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

```json
["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](/watchman/docs/cmd/state-enter.html) command, if the state name
matches any in the `defer` list then the subscription will emit a unilateral
subscription PDU like this:

```json
{
  "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](/watchman/docs/cmd/state-leave.html) 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:

```json
{
  "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

```json
["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](/watchman/docs/scm-query.html)