blob: 9f4dabbf3a2164aad8bbb12ed36d33e1bfb18219 [file] [log] [blame]
// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
import {Message} from 'google-protobuf';
import {Status} from 'pigweed/pw_status/ts/status';
import {PendingCalls, Rpc} from './rpc_classes';
export type Callback = (a: any) => any;
/** Represent an in-progress or completed RPC call. */
export class Call {
private rpcs: PendingCalls;
private rpc: Rpc;
private onNext: Callback;
private onCompleted: Callback;
private onError: Callback;
// TODO(jaredweinstein): support async timeout.
// private timeout: number;
private status?: Status;
error?: Status;
callbackException?: Error;
constructor(
rpcs: PendingCalls,
rpc: Rpc,
onNext: Callback,
onCompleted: Callback,
onError: Callback) {
this.rpcs = rpcs;
this.rpc = rpc;
this.onNext = onNext;
this.onCompleted = onCompleted;
this.onError = onError;
}
/* Calls the RPC. This must be called immediately after construction. */
invoke(request?: Message): void {
const previous = this.rpcs.sendRequest(this.rpc, this, request);
if (previous !== undefined && !previous.completed()) {
previous.handleError(Status.CANCELLED)
}
}
private invokeCallback(f: any) {
try {
f();
} catch (err) {
console.error(
`An exception was raised while invoking a callback: ${err}`);
this.callbackException = err
}
}
completed(): boolean {
return (this.status !== undefined || this.error !== undefined);
}
handleResponse(response: Message): void {
const callback = () => this.onNext(response);
this.invokeCallback(callback)
}
handleCompletion(status: Status) {
const callback = () => this.onCompleted(status);
this.invokeCallback(callback)
}
cancel(): boolean {
if (this.completed()) {
return false;
}
this.error = Status.CANCELLED
return this.rpcs.sendCancel(this.rpc);
}
handleError(error: Status): void {
this.error = error
const callback = () => this.onError(2);
this.invokeCallback(callback);
}
}
/** Tracks the state of a unary RPC call. */
export class UnaryCall extends Call {
// TODO(jaredweinstein): Complete unary invocation logic.
}
/** Tracks the state of a client streaming RPC call. */
export class ClientStreamingCall extends Call {
// TODO(jaredweinstein): Complete client streaming invocation logic.
}
/** Tracks the state of a server streaming RPC call. */
export class ServerStreamingCall extends Call {
// TODO(jaredweinstein): Complete server streaming invocation logic.
}
/** Tracks the state of a bidirectional streaming RPC call. */
export class BidirectionalStreamingCall extends Call {
// TODO(jaredweinstein): Complete bidirectional streaming invocation logic.
}