You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+40-40
Original file line number
Diff line number
Diff line change
@@ -4,8 +4,8 @@ The `ZeroBackpressureSemaphore` class implements a semaphore for Node.js project
4
4
This implementation does not queue pending jobs, thereby eliminating backpressure. As a result, users have better control over memory footprint, which enhances performance by reducing garbage-collector overhead.
5
5
6
6
The design addresses the two primary semaphore use cases in Node.js:
7
-
*__Single Job Execution__: In scenarios where multiple callers, such as route handlers, concurrently access the same semaphore instance. Each caller initiates a single job and relies on its outcome to proceed.
8
7
*__Multiple Jobs Execution__: This use case involves a single caller dispatching multiple jobs, often serving as the sole owner of the semaphore instance.
8
+
*__Single Job Execution__: In scenarios where multiple callers, such as route handlers, concurrently access the same semaphore instance. Each caller initiates a single job and relies on its outcome to proceed.
9
9
10
10
Each use case necessitates distinct handling capabilities, which will be discussed separately with accompanying examples.
11
11
@@ -33,44 +33,9 @@ npm i zero-backpressure-semaphore-typescript
33
33
- High efficiency: All state-altering operations have a constant time complexity, O(1).
34
34
- No external runtime dependencies: Only development dependencies are used.
35
35
36
-
## 1st use-case: Single Job Execution
37
-
38
-
The `waitForCompletion` method is useful for executing a sub-procedure, for which the caller must wait before proceeding with its work.
39
-
40
-
For example, consider fetching data from an external resource within a route handler. The route handler must respond (e.g., with an HTTP status 200 on success) based on the result of the fetching sub-procedure. Note that a sub-procedure may return a value or throw an error. If an error is thrown, `waitForCompletion` will propagate the error back to the caller.
41
-
42
-
The concurrency limit for such operations is typically set based on external constraints (e.g., reducing the chances of being throttled) or the desire to limit network resource usage.
logger.error(`Failed fetching user info for userID ${req.userID} with error: ${err.message}`);
66
-
res.status(HTTP_ERROR_CODE);
67
-
}
68
-
});
69
-
```
70
-
71
-
## 2nd use-case: Multiple Jobs Execution
36
+
## 1st use-case: Multiple Jobs Execution
72
37
73
-
Unlike the first use case, dispatching multiple concurrent jobs is more likely to cause backpressure. This pattern is typically observed in **background job services**, such as:
38
+
This semaphore variant excels in eliminating backpressure when dispatching multiple concurrent jobs from the same caller. This pattern is typically observed in **background job services**, such as:
74
39
- Log File analysis.
75
40
- Network Traffic analyzers.
76
41
- Vulnerability scanning.
@@ -79,10 +44,10 @@ Unlike the first use case, dispatching multiple concurrent jobs is more likely t
79
44
- Remote Configuration changes.
80
45
- Batch Data processing.
81
46
82
-
Here, the start time of each job is crucial. Since a pending job cannot start its execution until the semaphore allows, there is no benefit to adding additional jobs that cannot start immediately. The `startExecution` method communicates the job's start time to the caller (resolves as soon as the job starts), which enables to push a new job as-soon-as it makes sense.
47
+
Here, the start time of each job is crucial. Since a pending job cannot start its execution until the semaphore allows, there is no benefit to adding additional jobs that cannot start immediately. The `startExecution` method communicates the job's start time to the caller (resolves as soon as the job starts), which enables to create a new job as-soon-as it makes sense.
83
48
84
49
For example, consider an application managing 100,000 IoT sensors that require hourly data aggregation. To mitigate server load, a semaphore can be employed to limit the number of concurrent data aggregation tasks.
85
-
Rather than pre-creating 100,000 jobs (one for each sensor), which could potentially overwhelm the Node.js task queue and induce backpressure, the system should adopt a just-in-time approach. This means creating a sensor aggregation job only when the semaphore indicates availability, thereby optimizing resource utilization and maintaining system stability.
50
+
Rather than pre-creating 100,000 jobs (one for each sensor), which could potentially overwhelm the Node.js task queue and induce backpressure, the system should adopt a **just-in-time** approach. This means creating a sensor aggregation job only when the semaphore indicates availability, thereby optimizing resource utilization and maintaining system stability.
86
51
87
52
Note: method `waitTillAllExecutingJobsAreSettled` can be used to perform post-processing, after all jobs have completed. It complements the typical use-cases of `startExecution`.
88
53
@@ -109,6 +74,41 @@ async function aggregateSensorsData(sensorUIDs: ReadonlyArray<string>) {
109
74
}
110
75
```
111
76
77
+
## 2nd use-case: Single Job Execution
78
+
79
+
The `waitForCompletion` method is useful for executing a sub-procedure, for which the caller must wait before proceeding with its work.
80
+
81
+
For example, consider fetching data from an external resource within a route handler. The route handler must respond (e.g., with an HTTP status 200 on success) based on the result of the fetching sub-procedure. Note that a sub-procedure may return a value or throw an error. If an error is thrown, `waitForCompletion` will propagate the error back to the caller.
82
+
83
+
The concurrency limit for such operations is typically set based on external constraints (e.g., reducing the chances of being throttled) or the desire to limit network resource usage.
logger.error(`Failed fetching user info for userID ${req.userID} with error: ${err.message}`);
107
+
res.status(HTTP_ERROR_CODE);
108
+
}
109
+
});
110
+
```
111
+
112
112
## Graceful Termination
113
113
114
114
The `waitTillAllExecutingJobsAreSettled` method is essential for scenarios where it is necessary to wait for all ongoing jobs to finish, such as logging a success message or executing subsequent logic.
0 commit comments