Skip to content

Commit 186deca

Browse files
committed
Interface and flag specification for worker cancellation.
See design doc https://docs.google.com/document/d/1-h4gcBV8Jn6DK9G_e23kZQ159jmX__uckhub1Gv9dzc/edit Also fixes the JSON protocol processor to ignore unknown fields, as per spec. RELNOTES: Updates worker protocol with cancellation fields, and adds experimental_worker_cancellation flag to control cancellation. PiperOrigin-RevId: 367600226
1 parent 04cbf71 commit 186deca

File tree

6 files changed

+54
-11
lines changed

6 files changed

+54
-11
lines changed

src/main/java/com/google/devtools/build/lib/actions/ExecutionRequirements.java

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ public String parseIfMatches(String tag) throws ValidationException {
160160
/** Specify the type of worker protocol the worker uses. */
161161
public static final String REQUIRES_WORKER_PROTOCOL = "requires-worker-protocol";
162162

163+
public static final String SUPPORTS_WORKER_CANCELLATION = "supports-worker-cancellation";
164+
163165
/** Denotes what the type of worker protocol the worker uses. */
164166
public enum WorkerProtocolFormat {
165167
JSON,

src/main/java/com/google/devtools/build/lib/actions/Spawns.java

+5
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ public static boolean supportsMultiplexWorkers(Spawn spawn) {
9292
.equals(spawn.getExecutionInfo().get(ExecutionRequirements.SUPPORTS_MULTIPLEX_WORKERS));
9393
}
9494

95+
public static boolean supportsWorkerCancellation(Spawn spawn) {
96+
return "1"
97+
.equals(spawn.getExecutionInfo().get(ExecutionRequirements.SUPPORTS_WORKER_CANCELLATION));
98+
}
99+
95100
/**
96101
* Returns which worker protocol format a Spawn claims a persistent worker uses. Defaults to proto
97102
* if the protocol format is not specified.

src/main/java/com/google/devtools/build/lib/worker/JsonWorkerProtocol.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,12 @@ private WorkResponse parseResponse() throws IOException {
9292
requestId = reader.nextInt();
9393
break;
9494
default:
95-
throw new IOException(name + " is an incorrect field in work response");
95+
// As per https://docs.bazel.build/versions/master/creating-workers.html#work-responses,
96+
// unknown fields are ignored.
97+
reader.skipValue();
9698
}
9799
}
98-
reader.endObject();
100+
reader.endObject();
99101
} catch (MalformedJsonException | EOFException | IllegalStateException e) {
100102
throw new IOException("Could not parse json work request correctly", e);
101103
}

src/main/java/com/google/devtools/build/lib/worker/WorkerOptions.java

+8
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,12 @@ public String getTypeDescription() {
178178
"Currently a no-op. Future: If enabled, workers that support the experimental"
179179
+ " multiplexing feature will use that feature.")
180180
public boolean workerMultiplex;
181+
182+
@Option(
183+
name = "experimental_worker_cancellation",
184+
defaultValue = "false",
185+
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
186+
effectTags = {OptionEffectTag.EXECUTION},
187+
help = "If enabled, Bazel may send cancellation requests to workers that support them.")
188+
public boolean workerCancellation;
181189
}

src/main/protobuf/worker_protocol.proto

+24-6
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,19 @@ message WorkRequest {
3939
// request.
4040
repeated Input inputs = 2;
4141

42-
// To support multiplex worker, each WorkRequest must have an unique ID. This
43-
// ID should be attached unchanged to the WorkResponse.
42+
// Each WorkRequest must have either a unique
43+
// request_id or request_id = 0. If request_id is 0, this WorkRequest must be
44+
// processed alone, otherwise the worker may process multiple WorkRequests in
45+
// parallel (multiplexing). As an exception to the above, if the cancel field
46+
// is true, the request_id must be the same as a previously sent WorkRequest.
47+
// The request_id must be attached unchanged to the corresponding
48+
// WorkResponse.
4449
int32 request_id = 3;
50+
51+
// EXPERIMENTAL: When true, this is a cancel request, indicating that a
52+
// previously sent WorkRequest with the same request_id should be cancelled.
53+
// The arguments and inputs fields must be empty and should be ignored.
54+
bool cancel = 4;
4555
}
4656

4757
// The worker sends this message to Blaze when it finished its work on the
@@ -54,9 +64,17 @@ message WorkResponse {
5464
// string type here, which gives us UTF-8 encoding.
5565
string output = 2;
5666

57-
// To support multiplex worker, each WorkResponse must have an unique ID.
58-
// Since worker processes which support multiplex worker will handle multiple
59-
// WorkRequests in parallel, this ID will be used to determined which
60-
// WorkerProxy does this WorkResponse belong to.
67+
// This field must be set to the same request_id as the WorkRequest it is a
68+
// response to. Since worker processes which support multiplex worker will
69+
// handle multiple WorkRequests in parallel, this ID will be used to
70+
// determined which WorkerProxy does this WorkResponse belong to.
6171
int32 request_id = 3;
72+
73+
// EXPERIMENTAL When true, indicates that this response was sent due to
74+
// receiving a cancel request. The exit_code and output fields should be empty
75+
// and will be ignored. Exactly one WorkResponse must be sent for each
76+
// non-cancelling WorkRequest received by the worker, but if the worker
77+
// received a cancel request, it doesn't matter if it replies with a regular
78+
// WorkResponse or with one where was_cancelled = true.
79+
bool was_cancelled = 4;
6280
}

src/test/java/com/google/devtools/build/lib/worker/WorkerTest.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,16 @@ public void testGetResponse_json_multipleRequestId_fails() throws IOException {
199199
}
200200

201201
@Test
202-
public void testGetResponse_json_incorrectFields_fails() throws IOException {
203-
verifyGetResponseFailure(
204-
"{\"testField\":0}", "testField is an incorrect field in work response");
202+
public void testGetResponse_json_unknownFieldsIgnored() throws IOException, InterruptedException {
203+
TestWorker testWorker =
204+
createTestWorker(
205+
"{\"exitCode\":1,\"output\":\"test output\",\"requestId\":1,\"unknown\":{1:['a']}}"
206+
.getBytes(UTF_8),
207+
JSON);
208+
WorkResponse readResponse = testWorker.getResponse(1);
209+
WorkResponse response =
210+
WorkResponse.newBuilder().setExitCode(1).setOutput("test output").setRequestId(1).build();
211+
212+
assertThat(readResponse).isEqualTo(response);
205213
}
206214
}

0 commit comments

Comments
 (0)