Skip to content

Commit 449af24

Browse files
committed
refactor(fs): Add Switch reader
1 parent bb566fd commit 449af24

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

packages/fs/lib/readers/Switch.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import AbstractReader from "../AbstractReader.js";
2+
3+
/**
4+
* Reader allowing to switch its underlying reader at runtime.
5+
* If no reader is set, read operations will be halted/paused until a reader is set.
6+
*/
7+
export default class Switch extends AbstractReader {
8+
#reader;
9+
#pendingCalls = [];
10+
11+
constructor({name, reader}) {
12+
super(name);
13+
this.#reader = reader;
14+
}
15+
16+
/**
17+
* Sets the underlying reader and processes any pending read operations.
18+
*
19+
* @param {@ui5/fs/AbstractReader} reader The reader to delegate to.
20+
*/
21+
setReader(reader) {
22+
this.#reader = reader;
23+
this._processPendingCalls();
24+
}
25+
26+
/**
27+
* Unsets the underlying reader. Future calls will be queued.
28+
*/
29+
unsetReader() {
30+
this.#reader = null;
31+
}
32+
33+
async _byGlob(virPattern, options, trace) {
34+
if (this.#reader) {
35+
return this.#reader._byGlob(virPattern, options, trace);
36+
}
37+
38+
// No reader set, so we queue the call and return a pending promise
39+
return this._enqueueCall("_byGlob", [virPattern, options, trace]);
40+
}
41+
42+
43+
async _byPath(virPath, options, trace) {
44+
if (this.#reader) {
45+
return this.#reader._byPath(virPath, options, trace);
46+
}
47+
48+
// No reader set, so we queue the call and return a pending promise
49+
return this._enqueueCall("_byPath", [virPath, options, trace]);
50+
}
51+
52+
/**
53+
* Queues a method call by returning a promise and storing its resolver.
54+
*
55+
* @param {string} methodName The method name to call later.
56+
* @param {Array} args The arguments to pass to the method.
57+
* @returns {Promise} A promise that will be resolved/rejected when the call is processed.
58+
*/
59+
_enqueueCall(methodName, args) {
60+
return new Promise((resolve, reject) => {
61+
this.#pendingCalls.push({methodName, args, resolve, reject});
62+
});
63+
}
64+
65+
/**
66+
* Processes all pending calls in the queue using the current reader.
67+
*
68+
* @private
69+
*/
70+
_processPendingCalls() {
71+
const callsToProcess = this.#pendingCalls;
72+
this.#pendingCalls = []; // Clear queue immediately to prevent race conditions
73+
74+
for (const call of callsToProcess) {
75+
const {methodName, args, resolve, reject} = call;
76+
// Execute the pending call with the newly set reader
77+
this.#reader[methodName](...args)
78+
.then(resolve)
79+
.catch(reject);
80+
}
81+
}
82+
}

packages/fs/lib/resourceFactory.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import WriterCollection from "./WriterCollection.js";
1010
import Filter from "./readers/Filter.js";
1111
import Link from "./readers/Link.js";
1212
import Proxy from "./readers/Proxy.js";
13+
import Switch from "./readers/Switch.js";
1314
import MonitoredReader from "./MonitoredReader.js";
1415
import MonitoredReaderWriter from "./MonitoredReaderWriter.js";
1516
import {getLogger} from "@ui5/logger";
@@ -277,6 +278,19 @@ export function createFlatReader({name, reader, namespace}) {
277278
});
278279
}
279280

281+
export function createSwitch({name, reader}) {
282+
return new Switch({
283+
name,
284+
reader: reader,
285+
});
286+
}
287+
288+
/**
289+
* Creates a monitored reader or reader-writer depending on the provided instance
290+
* of the given readerWriter.
291+
*
292+
* @param {@ui5/fs/AbstractReader|@ui5/fs/AbstractReaderWriter} readerWriter Reader or ReaderWriter to monitor
293+
*/
280294
export function createMonitor(readerWriter) {
281295
if (readerWriter instanceof DuplexCollection) {
282296
return new MonitoredReaderWriter(readerWriter);

0 commit comments

Comments
 (0)