-
Notifications
You must be signed in to change notification settings - Fork 132
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce LockManager for Async Handling and Optimize PUML Diagrams (#…
…2345) Introduce LockManager for Async Handling and Optimize PUML Diagrams Introduce the LockManager module to manage the lifecycle of asynchronous functions, ensuring robust and consistent handling within synchronous methods. Utilize the createLock, deleteLock, and waitForLockRelease methods for starting, stopping, and waiting for async functions respectively. Code snippet: ```javascript const LockManager = require('path_to/LockManager'); const lockId = LockManager.createLock(); LockManager.deleteLock(lockId); await LockManager.waitForLockRelease(); ``` Fix the issue where all distinct PUML diagrams were being reprocessed on every hot reload by introducing a hashmap tracker. - The hash key comes from the content and the file name of the PUML diagram. By implementing these changes, the code is made more maintainable, asynchronous functions are properly managed, and PUML diagram processing is optimized.
- Loading branch information
Showing
17 changed files
with
184 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { v4 as uuidv4 } from 'uuid'; | ||
|
||
/** | ||
* The `LockManager` is a singleton class designed to help wait for required async | ||
* promised operations to complete | ||
* before the page is generated. It provides functionalities to create, delete, and wait | ||
* for the release of locks. | ||
* The locks are stored in a Map with a unique ID (either provided or auto-generated) as | ||
* the key. | ||
* The class provides an instance property to get the singleton instance of `LockManager`. | ||
*/ | ||
|
||
class LockManager { | ||
// Holds the single instance of LockManager. | ||
private static _instance: LockManager; | ||
|
||
// A Map to keep track of the active locks. | ||
private locks: Map<string, boolean>; | ||
|
||
/** | ||
* Private constructor to prevent direct instantiation from outside. | ||
* Initializes the locks Map. | ||
*/ | ||
private constructor() { | ||
this.locks = new Map(); | ||
} | ||
|
||
/** | ||
* Provides a way to access the single instance of the LockManager. | ||
* If it doesn't exist, it creates one. | ||
* @returns {LockManager} The single instance of LockManager. | ||
*/ | ||
public static get instance() { | ||
if (!LockManager._instance) { | ||
LockManager._instance = new LockManager(); | ||
} | ||
|
||
return LockManager._instance; | ||
} | ||
|
||
/** | ||
* Creates a new lock. | ||
* @param {string} [id] - An optional ID to use for the lock. If not provided, a UUID will be generated. | ||
* @returns {string} The ID of the created lock. | ||
*/ | ||
createLock(id?: string): string { | ||
const lockId = id ?? uuidv4(); | ||
this.locks.set(lockId, true); | ||
return lockId; | ||
} | ||
|
||
/** | ||
* Deletes a lock by its ID. | ||
* @param {string} lockId - The ID of the lock to be deleted. | ||
*/ | ||
deleteLock(lockId: string): void { | ||
this.locks.delete(lockId); | ||
} | ||
|
||
/** | ||
* Deletes all locks, clearing the locks Map. | ||
*/ | ||
deleteAllLocks(): void { | ||
this.locks.clear(); | ||
} | ||
|
||
/** | ||
* Waits until all locks are released and then resolves. | ||
* @returns {Promise<void>} A promise that resolves when all locks are released. | ||
*/ | ||
waitForLockRelease(): Promise<void> { | ||
return new Promise((resolve) => { | ||
const checkLocks = () => { | ||
if (this.locks.size === 0) { | ||
resolve(); | ||
} else { | ||
setTimeout(checkLocks, 100); | ||
} | ||
}; | ||
checkLocks(); | ||
}); | ||
} | ||
} | ||
|
||
// Export the singleton instance of LockManager. | ||
export = LockManager.instance; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import LockManager from '../../../src/utils/LockManager'; | ||
|
||
describe('LockManager', () => { | ||
let lockManager: typeof LockManager; | ||
|
||
beforeEach(() => { | ||
lockManager = LockManager; | ||
}); | ||
|
||
afterEach(() => { | ||
lockManager.deleteAllLocks(); | ||
}); | ||
|
||
it('should create a new lock', () => { | ||
const lockId = lockManager.createLock(); | ||
expect(lockId).toBeDefined(); | ||
}); | ||
|
||
it('should use the provided ID when creating a lock', () => { | ||
const lockId = 'customId'; | ||
const createdLockId = lockManager.createLock(lockId); | ||
expect(createdLockId).toEqual(lockId); | ||
}); | ||
|
||
it('should delete all locks', () => { | ||
lockManager.createLock(); | ||
lockManager.createLock(); | ||
lockManager.deleteAllLocks(); | ||
}); | ||
|
||
it('should wait until all locks are released and resolve', async () => { | ||
const lockId1 = lockManager.createLock(); | ||
const lockId2 = lockManager.createLock(); | ||
|
||
const waitForLockReleasePromise = lockManager.waitForLockRelease(); | ||
|
||
setTimeout(() => lockManager.deleteLock(lockId1), 100); | ||
setTimeout(() => lockManager.deleteLock(lockId2), 200); | ||
|
||
await expect(waitForLockReleasePromise).resolves.toBeUndefined(); | ||
}); | ||
}); |