Skip to content

Commit e7a510e

Browse files
Remove duplicated logic
Signed-off-by: Xavier Geerinck <[email protected]>
1 parent 1070851 commit e7a510e

File tree

9 files changed

+69
-108
lines changed

9 files changed

+69
-108
lines changed

src/implementation/Client/DaprClient.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1010
See the License for the specific language governing permissions and
1111
limitations under the License.
1212
*/
13+
import * as NodeJSUtils from "../../utils/NodeJS.util";
1314

1415
import IClientBinding from '../../interfaces/Client/IClientBinding';
1516
import IClientPubSub from '../../interfaces/Client/IClientPubSub';
@@ -133,13 +134,43 @@ export default class DaprClient {
133134
await this.daprClient.stop();
134135
}
135136

137+
async awaitSidecarStarted(): Promise<void> {
138+
// Dapr will probe every 50ms to see if we are listening on our port: https://github.com/dapr/dapr/blob/a43712c97ead550ca2f733e9f7e7769ecb195d8b/pkg/runtime/runtime.go#L1694
139+
// if we are using actors we will change this to 4s to let the placement tables update
140+
let isHealthy = false;
141+
let isHealthyRetryCount = 0;
142+
const isHealthyMaxRetryCount = 60; // 1s startup delay and we try max for 60s
143+
144+
console.log(`[Dapr-JS][Client] Awaiting Sidecar to be Started`);
145+
while (!isHealthy) {
146+
console.log(`[Dapr-JS][Client] Waiting till Dapr Sidecar Started (#${isHealthyRetryCount})`);
147+
await NodeJSUtils.sleep(Settings.getDaprSidecarPollingDelayMs());
148+
149+
// Implement API call manually as we need to enable calling without initialization
150+
// everything routes through the `execute` method
151+
// to check health, we just ping the /metadata endpoint and see if we get a response
152+
isHealthy = await this.health.isHealthy();
153+
154+
// Finally, Handle the retry logic
155+
isHealthyRetryCount++;
156+
157+
if (isHealthyRetryCount > isHealthyMaxRetryCount) {
158+
throw new Error("DAPR_SIDECAR_COULD_NOT_BE_STARTED");
159+
}
160+
}
161+
}
162+
136163
/**
137-
* Ensure the sidecar connection has been initialized
138-
* this method is not mandatory to be utilized as we will
139-
* ensure the sidecar connection is initialized in the methods that require it
164+
* Ensure the client is started, this takes care of:
165+
* 1. Making sure the sidecar is started
166+
* 2. Making sure the connection is established (e.g. in gRPC)
167+
* 3. Making sure the client is ready to be used
140168
*/
141169
async start(): Promise<void> {
170+
await this.awaitSidecarStarted();
142171
await this.daprClient.start();
172+
await this.daprClient.setIsInitialized(true);
173+
console.log(`[Dapr-JS][Client] Sidecar Started`);
143174
}
144175

145176
getDaprClient(): IClient {

src/implementation/Client/GRPCClient/GRPCClient.ts

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ import IClient from "../../../interfaces/Client/IClient";
1717
import CommunicationProtocolEnum from "../../../enum/CommunicationProtocol.enum";
1818
import { DaprClientOptions } from "../../../types/DaprClientOptions";
1919
import { Settings } from '../../../utils/Settings.util';
20-
import * as NodeJSUtils from "../../../utils/NodeJS.util";
21-
import { Empty } from "google-protobuf/google/protobuf/empty_pb";
22-
import { GetMetadataResponse } from "../../../proto/dapr/proto/runtime/v1/dapr_pb";
2320

2421
export default class GRPCClient implements IClient {
2522
private isInitialized: boolean;
@@ -67,20 +64,8 @@ export default class GRPCClient implements IClient {
6764
return this.options;
6865
}
6966

70-
async isSidecarStarted(): Promise<boolean> {
71-
return new Promise((resolve, _reject) => {
72-
try {
73-
this.client.getMetadata(new Empty(), (err, _res: GetMetadataResponse) => {
74-
if (err) {
75-
return resolve(false);
76-
}
77-
78-
return resolve(true);
79-
});
80-
} catch (e) {
81-
return resolve(false);
82-
}
83-
});
67+
setIsInitialized(isInitialized: boolean): void {
68+
this.isInitialized = isInitialized;
8469
}
8570

8671
async stop(): Promise<void> {
@@ -93,6 +78,7 @@ export default class GRPCClient implements IClient {
9378
return new Promise((resolve, reject) => {
9479
this.client.waitForReady(deadline, (err?) => {
9580
if (err) {
81+
console.error(err);
9682
return reject();
9783
}
9884

@@ -103,33 +89,5 @@ export default class GRPCClient implements IClient {
10389

10490
async start(): Promise<void> {
10591
await this._startWaitForClientReady();
106-
107-
// Dapr will probe every 50ms to see if we are listening on our port: https://github.com/dapr/dapr/blob/a43712c97ead550ca2f733e9f7e7769ecb195d8b/pkg/runtime/runtime.go#L1694
108-
// if we are using actors we will change this to 4s to let the placement tables update
109-
let isHealthy = false;
110-
let isHealthyRetryCount = 0;
111-
const isHealthyMaxRetryCount = 60; // 1s startup delay and we try max for 60s
112-
113-
console.log(`[Dapr-JS][Client] Awaiting Sidecar to be Started`);
114-
while (!isHealthy) {
115-
console.log(`[Dapr-JS][Client] Waiting till Dapr Sidecar Started (#${isHealthyRetryCount})`);
116-
await NodeJSUtils.sleep(Settings.getDaprSidecarPollingDelayMs());
117-
118-
// Implement API call manually as we need to enable calling without initialization
119-
// everything routes through the `execute` method
120-
// to check health, we just ping the /metadata endpoint and see if we get a response
121-
isHealthy = await this.isSidecarStarted();
122-
123-
// Finally, Handle the retry logic
124-
isHealthyRetryCount++;
125-
126-
if (isHealthyRetryCount > isHealthyMaxRetryCount) {
127-
throw new Error("DAPR_SIDECAR_COULD_NOT_BE_STARTED");
128-
}
129-
}
130-
131-
// We are initialized
132-
this.isInitialized = true;
133-
console.log(`[Dapr-JS][Client] Sidecar Started`);
13492
}
13593
}

src/implementation/Client/GRPCClient/health.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ limitations under the License.
1313

1414
import GRPCClient from './GRPCClient';
1515
import IClientHealth from '../../../interfaces/Client/IClientHealth';
16+
import { GetMetadataResponse } from '../../../proto/dapr/proto/runtime/v1/dapr_pb';
17+
import { Empty } from "google-protobuf/google/protobuf/empty_pb";
1618

1719
// https://docs.dapr.io/reference/api/health_api/
1820
export default class GRPCClientHealth implements IClientHealth {
@@ -24,6 +26,20 @@ export default class GRPCClientHealth implements IClientHealth {
2426

2527
// There is no gRPC implementation of /healthz, so we try to fetch the metadata
2628
async isHealthy(): Promise<boolean> {
27-
return this.client.isSidecarStarted();
29+
return new Promise((resolve, _reject) => {
30+
const client = this.client.getClient();
31+
32+
try {
33+
client.getMetadata(new Empty(), (err, _res: GetMetadataResponse) => {
34+
if (err) {
35+
return resolve(false);
36+
}
37+
38+
return resolve(true);
39+
});
40+
} catch (e) {
41+
return resolve(false);
42+
}
43+
});
2844
}
2945
}

src/implementation/Client/HTTPClient/HTTPClient.ts

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import http from "http";
1818
import https from "https";
1919
import { DaprClientOptions } from "../../../types/DaprClientOptions";
2020
import { Settings } from '../../../utils/Settings.util';
21-
import * as NodeJSUtils from "../../../utils/NodeJS.util";
2221
import { THTTPExecuteParams } from "../../../types/http/THTTPExecuteParams.type"
2322

2423
export default class HTTPClient implements IClient {
@@ -89,48 +88,16 @@ export default class HTTPClient implements IClient {
8988
return this.options;
9089
}
9190

91+
setIsInitialized(isInitialized: boolean): void {
92+
this.isInitialized = isInitialized;
93+
}
94+
9295
async stop(): Promise<void> {
9396
this.httpAgent.destroy();
9497
this.httpsAgent.destroy();
9598
}
9699

97-
async isSidecarStarted(): Promise<boolean> {
98-
try {
99-
await this.execute(`/metadata`, null, false);
100-
return true;
101-
} catch (e) {
102-
return false;
103-
}
104-
}
105-
106100
async start(): Promise<void> {
107-
// Dapr will probe every 50ms to see if we are listening on our port: https://github.com/dapr/dapr/blob/a43712c97ead550ca2f733e9f7e7769ecb195d8b/pkg/runtime/runtime.go#L1694
108-
// if we are using actors we will change this to 4s to let the placement tables update
109-
let isHealthy = false;
110-
let isHealthyRetryCount = 0;
111-
const isHealthyMaxRetryCount = 60; // 1s startup delay and we try max for 60s
112-
113-
console.log(`[Dapr-JS][Client] Awaiting Sidecar to be Started`);
114-
while (!isHealthy) {
115-
console.log(`[Dapr-JS][Client] Waiting till Dapr Sidecar Started (#${isHealthyRetryCount})`);
116-
await NodeJSUtils.sleep(Settings.getDaprSidecarPollingDelayMs());
117-
118-
// Implement API call manually as we need to enable calling without initialization
119-
// everything routes through the `execute` method
120-
// to check health, we just ping the /metadata endpoint and see if we get a response
121-
isHealthy = await this.isSidecarStarted();
122-
123-
// Finally, Handle the retry logic
124-
isHealthyRetryCount++;
125-
126-
if (isHealthyRetryCount > isHealthyMaxRetryCount) {
127-
throw new Error("DAPR_SIDECAR_COULD_NOT_BE_STARTED");
128-
}
129-
}
130-
131-
// We are initialized
132-
this.isInitialized = true;
133-
console.log(`[Dapr-JS][Client] Sidecar Started`);
134101
}
135102

136103
async executeWithApiVersion(apiVersion = "v1.0", url: string, params: any = {}): Promise<object | string> {

src/implementation/Client/HTTPClient/health.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ export default class HTTPClientHealth implements IClientHealth {
2424

2525
// Send an event to an external system
2626
async isHealthy(): Promise<boolean> {
27-
return this.client.isSidecarStarted();
27+
try {
28+
const result = await this.client.execute(`/metadata`);
29+
return !!result;
30+
} catch (e) {
31+
return false;
32+
}
2833
}
2934
}

src/implementation/Server/DaprServer.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,24 +110,8 @@ export default class DaprServer {
110110
// First start the server as we need to initialize routes for PubSub, Bindings, ...
111111
await this.daprServer.start(this.serverHost, this.serverPort.toString());
112112

113-
// Ensure our sidecar starts
114-
// Dapr will probe every 50ms to see if we are listening on our port: https://github.com/dapr/dapr/blob/a43712c97ead550ca2f733e9f7e7769ecb195d8b/pkg/runtime/runtime.go#L1694
115-
// if we are using actors we will change this to 4s to let the placement tables update
116-
let isHealthy = false;
117-
let isHealthyRetryCount = 0;
118-
const isHealthyMaxRetryCount = 60; // 1s startup delay and we try max for 60s
119-
120-
console.log(`[Dapr-JS][Server] Awaiting Sidecar to be Started`);
121-
while (!isHealthy) {
122-
console.log(`[Dapr-JS][Server] Waiting till Dapr Sidecar Started (#${isHealthyRetryCount})`);
123-
await NodeJSUtils.sleep(Settings.getDaprSidecarPollingDelayMs());
124-
isHealthy = await this.client.getDaprClient().isSidecarStarted();
125-
isHealthyRetryCount++;
126-
127-
if (isHealthyRetryCount > isHealthyMaxRetryCount) {
128-
throw new Error("DAPR_SIDECAR_COULD_NOT_BE_STARTED");
129-
}
130-
}
113+
// Ensure our sidecar starts and the client is ready
114+
await this.client.start();
131115

132116
// We are initialized
133117
console.log(`[Dapr-JS][Server] Sidecar Started`);

src/interfaces/Client/IClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default interface IClient {
2020
getClientPort(): string;
2121
getClientCommunicationProtocol(): CommunicationProtocolEnum;
2222
getOptions(): DaprClientOptions;
23-
isSidecarStarted(): Promise<boolean>;
23+
setIsInitialized(isInitialized: boolean): void;
2424
stop(): Promise<void>;
2525
start(): Promise<void>;
2626
}

test/e2e/grpc/client.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('grpc/client', () => {
3737
// there is however a delay between the sidecar being ready and the app starting as they are started asynchronously
3838
// if Dapr has to connect to a component, it might introduce a delay
3939
// the test will thus randomly have isStarted = true or isStarted = false depending on the startup delay of the sidecar
40-
await client.getDaprClient().isSidecarStarted();
40+
await client.health.isHealthy();
4141
// expect(isStarted).toBe(false);
4242
})
4343
});

test/e2e/http/client.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('http/client', () => {
3939
// there is however a delay between the sidecar being ready and the app starting as they are started asynchronously
4040
// if Dapr has to connect to a component, it might introduce a delay
4141
// the test will thus randomly have isStarted = true or isStarted = false depending on the startup delay of the sidecar
42-
await client.getDaprClient().isSidecarStarted();
42+
await client.health.isHealthy();
4343
// expect(isStarted).toBe(false);
4444
})
4545
});

0 commit comments

Comments
 (0)