Skip to content

Commit d800286

Browse files
committed
fix(*): fix queue
1 parent 1538395 commit d800286

File tree

11 files changed

+74
-86
lines changed

11 files changed

+74
-86
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,10 @@ const pathfinding = new Pathfinding(
4141

4242
- `config` - _Pathfinding configuration_
4343

44-
| Prop | Description | Default |
45-
| --------------- | ---------------------- | ------- |
46-
| loopRate | Finding next task rate | 100 ms |
47-
| taskProcessRate | Processing task rate | 0 ms |
48-
| resourceLimits | Worker resource limits | - |
44+
| Prop | Description | Default |
45+
| -------------- | ---------------------- | ------- |
46+
| loopRate | Finding next task rate | 200 ms |
47+
| resourceLimits | Worker resource limits | - |
4948

5049
### ⚡️ Terminate worker thread
5150

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/pathfinding/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export declare class Pathfinding {
1212
*
1313
* @param config - Pathfinding configuration
1414
*/
15-
constructor({ loopRate, taskProcessRate, resourceLimits }?: PathfindingConfig);
15+
constructor({ loopRate, resourceLimits }?: PathfindingConfig);
1616
/**
1717
* Terminate worker thread.
1818
*/

dist/pathfinding/types.d.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@ import type { ResourceLimits } from 'worker_threads';
22
export type PathfindingConfig = {
33
/**
44
* Finding next task rate
5-
* Default: 100 ms
5+
* Default: 200 ms
66
*/
77
loopRate?: number;
8-
/**
9-
* Processing task rate
10-
* Default: 0 ms
11-
*/
12-
taskProcessRate?: number;
138
/**
149
* Worker resource limits
1510
*/

dist/process/types.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export type PathfindingProcessConfig = {
22
loopRate?: number;
3-
taskProcessRate?: number;
43
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "pathfinding-worker",
33
"description": "Fast node.js pathfinding on workers for grid-based games",
4-
"version": "2.5.2",
4+
"version": "2.6.0",
55
"keywords": [
66
"astar",
77
"dijkstra",
@@ -26,7 +26,7 @@
2626
"build": "yarn build:worker && yarn build:entrypoint",
2727
"build:worker": "webpack --config ./webpack/worker.config.js --mode production",
2828
"build:entrypoint": "webpack --config ./webpack/entrypoint.config.js --mode production",
29-
"test": "jest",
29+
"test": "yarn build && jest",
3030
"lint": "eslint \"./src/**/*.ts\" --fix"
3131
},
3232
"dependencies": {

src/pathfinding/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export class Pathfinding {
2020
*
2121
* @param config - Pathfinding configuration
2222
*/
23-
constructor({ loopRate, taskProcessRate, resourceLimits }: PathfindingConfig = {}) {
23+
constructor({ loopRate, resourceLimits }: PathfindingConfig = {}) {
2424
this.worker = new Worker(INLINE_WORKER, {
2525
name: 'pathfinding',
2626
eval: true,
27-
workerData: { loopRate, taskProcessRate },
27+
workerData: { loopRate },
2828
resourceLimits,
2929
});
3030

src/pathfinding/types.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@ import type { ResourceLimits } from 'worker_threads';
33
export type PathfindingConfig = {
44
/**
55
* Finding next task rate
6-
* Default: 100 ms
6+
* Default: 200 ms
77
*/
88
loopRate?: number;
99

10-
/**
11-
* Processing task rate
12-
* Default: 0 ms
13-
*/
14-
taskProcessRate?: number;
15-
1610
/**
1711
* Worker resource limits
1812
*/

src/process/const.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const PATHFINDING_PROCESS_LOOP_RATE = 100;
66
/**
77
* @internal
88
*/
9-
export const PATHFINDING_PROCESS_TASK_PROCESS_RATE = 0;
9+
export const PATHFINDING_PROCESS_TASK_HANDLING_MAX_STACK_SIZE = 128;
1010

1111
/**
1212
* @internal

src/process/index.ts

Lines changed: 61 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
PATHFINDING_PROCESS_LOOP_RATE,
33
PATHFINDING_PROCESS_NEXT_DIRECTIINS_DIAGONAL,
44
PATHFINDING_PROCESS_NEXT_DIRECTIINS_STRAIGHT,
5-
PATHFINDING_PROCESS_TASK_PROCESS_RATE,
5+
PATHFINDING_PROCESS_TASK_HANDLING_MAX_STACK_SIZE,
66
} from './const';
77

88
import type { PathfindingProcessConfig } from './types';
@@ -21,26 +21,27 @@ export class PathfindingProcess {
2121

2222
private queue: PathfindingTask[] = [];
2323

24-
private timer: NodeJS.Timeout | null = null;
24+
private readonly timer: NodeJS.Timeout;
2525

26-
private readonly taskProcessRate: number;
27-
28-
private readonly loopRate: number;
26+
private processing: boolean = false;
2927

3028
constructor({
31-
taskProcessRate = PATHFINDING_PROCESS_TASK_PROCESS_RATE,
3229
loopRate = PATHFINDING_PROCESS_LOOP_RATE,
3330
}: PathfindingProcessConfig) {
34-
this.taskProcessRate = taskProcessRate;
35-
this.loopRate = loopRate;
36-
37-
this.handleTask();
31+
this.timer = setInterval(() => {
32+
try {
33+
if (!this.processing) {
34+
this.processing = true;
35+
this.handleTask();
36+
}
37+
} catch (error) {
38+
console.error('Pathfinding process error:', error);
39+
}
40+
}, loopRate);
3841
}
3942

4043
public destroy(): void {
41-
if (this.timer) {
42-
clearTimeout(this.timer);
43-
}
44+
clearTimeout(this.timer);
4445
}
4546

4647
public createTask(task: PathfindingTask): void {
@@ -101,76 +102,77 @@ export class PathfindingProcess {
101102
grid[position.y][position.x] = state;
102103
}
103104

104-
private handleTask(): void {
105+
private handleTask(stackSize: number = 0): void {
105106
const task = this.queue[0];
106107
if (!task) {
107-
this.timer = setTimeout(() => {
108-
this.timer = null;
109-
this.handleTask();
110-
}, this.loopRate);
108+
this.processing = false;
111109
return;
112110
}
113111

114112
const next = () => {
115-
setTimeout(() => {
116-
this.handleTask();
117-
}, this.taskProcessRate);
113+
if (stackSize >= PATHFINDING_PROCESS_TASK_HANDLING_MAX_STACK_SIZE) {
114+
setTimeout(() => {
115+
this.handleTask();
116+
});
117+
} else {
118+
this.handleTask(stackSize + 1);
119+
}
118120
};
119121

120122
const complete = (result: PathfindingTaskResultRaw) => {
121123
this.queue.shift();
122124
task.complete(result);
125+
this.processing = false;
123126
};
124127

125128
try {
126129
const currentNode = task.takeLastNode();
127-
if (currentNode) {
128-
if (task.isVisited(currentNode.position)) {
129-
next();
130+
if (!currentNode) {
131+
return complete({
132+
path: null,
133+
weight: Infinity,
134+
});
135+
}
136+
137+
if (task.isVisited(currentNode.position)) {
138+
return next();
139+
}
140+
141+
task.markVisited(currentNode.position);
142+
143+
if (
144+
currentNode.position.x === task.to.x &&
145+
currentNode.position.y === task.to.y
146+
) {
147+
return complete(currentNode.compute());
148+
}
149+
150+
this.getNextDirections(task, currentNode).forEach((offset) => {
151+
const position = {
152+
x: currentNode.position.x + offset.x,
153+
y: currentNode.position.y + offset.y,
154+
};
155+
156+
if (task.isVisited(position)) {
130157
return;
131158
}
132159

133-
task.markVisited(currentNode.position);
160+
const weights = this.weights.get(task.idLayer) ?? [];
161+
const nextWeight = task.getNextWeight(currentNode, offset, weights);
162+
const nextNode = task.pickNode(position);
134163

135-
if (
136-
currentNode.position.x === task.to.x &&
137-
currentNode.position.y === task.to.y
138-
) {
139-
complete(currentNode.compute());
164+
if (nextNode) {
165+
if (nextWeight < nextNode.getWeight()) {
166+
task.rewriteNode(currentNode, nextNode, nextWeight);
167+
}
140168
} else {
141-
this.getNextDirections(task, currentNode).forEach((offset) => {
142-
const position = {
143-
x: currentNode.position.x + offset.x,
144-
y: currentNode.position.y + offset.y,
145-
};
146-
147-
if (task.isVisited(position)) {
148-
return;
149-
}
150-
151-
const weights = this.weights.get(task.idLayer) ?? [];
152-
const nextWeight = task.getNextWeight(currentNode, offset, weights);
153-
const nextNode = task.pickNode(position);
154-
155-
if (nextNode) {
156-
if (nextWeight < nextNode.getWeight()) {
157-
task.rewriteNode(currentNode, nextNode, nextWeight);
158-
}
159-
} else {
160-
task.addNode(currentNode, position, nextWeight);
161-
}
162-
});
169+
task.addNode(currentNode, position, nextWeight);
163170
}
164-
} else {
165-
complete({
166-
path: null,
167-
weight: Infinity,
168-
});
169-
}
171+
});
170172

171173
next();
172174
} catch (error) {
173-
console.error('Pathfinding process error:', error);
175+
console.error('Pathfinding handle task error:', error);
174176
complete({
175177
path: null,
176178
weight: Infinity,

0 commit comments

Comments
 (0)