in src/lease.ts [312:364]
private keepalive() {
// When the cluster goes down, we keep trying to reconnect. But if we're
// far past the end of our key's TTL, there's no way we're going to be
// able to renew it. Fire a "lost".
if (Date.now() - this.lastKeepAlive > 2 * 1000 * this.ttl) {
this.close();
this.emit(
'lost',
new EtcdLeaseInvalidError('We lost connection to etcd and our lease has expired.'),
);
return;
}
this.client
.leaseKeepAlive()
.then(stream => {
if (this.innerState === LeaseState.Revoked) {
return stream.end();
}
// this is what the official Go client uses, good enough:
const keepAliveInterval = (1000 * this.ttl) / 3;
const keepaliveTimer = setInterval(() => this.fireKeepAlive(stream), keepAliveInterval);
const keepAliveTimeout = debounce(1000 * this.ttl, () =>
this.handleKeepaliveError(new GRPCCancelledError('GRPC watch stream has timed out.')),
);
this.teardown = () => {
this.teardown = () => undefined;
keepAliveTimeout.cancel();
clearInterval(keepaliveTimer);
stream.end();
};
keepAliveTimeout(); // start the debounce
stream
.on('error', err => this.handleKeepaliveError(err))
.on('data', res => {
if (leaseExpired(res)) {
return this.handleKeepaliveError(new EtcdLeaseInvalidError(res.ID));
}
this.lastKeepAlive = Date.now();
keepAliveTimeout();
this.emit('keepaliveSucceeded', res);
});
this.emit('keepaliveEstablished');
return this.fireKeepAlive(stream);
})
.catch(err => this.handleKeepaliveError(err));
}