-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbes.ts
More file actions
118 lines (104 loc) · 3.72 KB
/
bes.ts
File metadata and controls
118 lines (104 loc) · 3.72 KB
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
import * as vscode from 'vscode';
import * as grpc from '@grpc/grpc-js';
import * as loader from '@grpc/proto-loader';
import { Container } from '../container';
import { ProtoGrpcType as PublishBuildEventServiceProtoType } from '../proto/publish_build_event';
import { BuildEventServiceConfiguration, BuildEventServiceSettings } from './configuration';
import { GRPCClient } from './grpcclient';
import { getGRPCCredentials } from './proto';
import { DisabledError, RunnableComponent, Status } from './status';
import { PublishBuildEventClient } from '../proto/google/devtools/build/v1/PublishBuildEvent';
import { Empty } from '../proto/google/protobuf/Empty';
import { PublishLifecycleEventRequest } from '../proto/google/devtools/build/v1/PublishLifecycleEventRequest';
import { Bzl } from './bzl';
function loadPublishBuildEventServiceProtos(protofile: string): PublishBuildEventServiceProtoType {
const protoPackage = loader.loadSync(protofile, {
keepCase: false,
defaults: false,
oneofs: true,
});
return grpc.loadPackageDefinition(protoPackage) as unknown as PublishBuildEventServiceProtoType;
}
class PBEClient extends GRPCClient {
public readonly pbe: PublishBuildEventClient;
constructor(
uri: vscode.Uri,
creds: grpc.ChannelCredentials,
proto: PublishBuildEventServiceProtoType,
onError: (err: grpc.ServiceError) => void
) {
super(onError);
this.pbe = this.addCloseable(
new proto.google.devtools.build.v1.PublishBuildEvent(uri.authority, creds)
);
}
async publishLifecycleEvent(
req: PublishLifecycleEventRequest,
waitForReady = false,
deadlineSeconds = 3
): Promise<Empty> {
return new Promise<Empty>((resolve, reject) => {
this.pbe.PublishLifecycleEvent(
req,
new grpc.Metadata({ waitForReady: waitForReady }),
{ deadline: this.getDeadline(deadlineSeconds) },
(err?: grpc.ServiceError, resp?: Empty) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(resp!);
}
}
);
});
}
}
export class BuildEventService extends RunnableComponent<BuildEventServiceConfiguration> {
constructor(
public readonly settings: BuildEventServiceSettings,
public readonly bzl: Bzl,
private readonly proto = loadPublishBuildEventServiceProtos(
settings.configCtx.protoFile('publish_build_event.proto').fsPath
)
) {
super('BES', settings);
bzl.onDidChangeStatus(this.restart, this, this.disposables);
}
async startInternal(): Promise<void> {
if (this.bzl.status !== Status.READY) {
throw new DisabledError('Bzl not ready');
}
const cfg = await this.settings.get();
const creds = getGRPCCredentials(cfg.backendAddress.authority);
return new Promise((resolve, reject) => {
const client = new PBEClient(cfg.backendAddress, creds, this.proto, e => this.handleGrpcError(e));
const stream = client.pbe.publishBuildToolEventStream(new grpc.Metadata());
stream.on('error', (err: grpc.ServiceError) => {
const grpcErr: grpc.ServiceError = err as grpc.ServiceError;
if (grpcErr.code === grpc.status.INVALID_ARGUMENT) {
resolve();
} else {
reject(err);
}
});
// Intentionally write an empty / invalid request and expect
// server responds with InvalidArgument.
stream.write({}, (args: any) => {
if (args) {
console.log('bes write args', args);
}
});
});
}
async stopInternal(): Promise<void> { }
private handleGrpcError(err: grpc.ServiceError) {
if (this.status !== Status.READY) {
return;
}
switch (err.code) {
case grpc.status.UNAVAILABLE:
this.restart();
break;
}
}
}