fix: add timeout for device responses

This commit is contained in:
2024-03-05 18:12:56 +01:00
parent 7256dc50d4
commit 6ac2cd1993
3 changed files with 68 additions and 46 deletions

View File

@@ -40,6 +40,16 @@ export async function canAutoConnect() {
return getViablePorts().then(it => it.length === 1) return getViablePorts().then(it => it.length === 1)
} }
function timeout<T>(promise: Promise<T>, ms: number): Promise<T> {
let timer: number
return Promise.race([
promise,
new Promise<T>((_, reject) => {
timer = setTimeout(() => reject(new Error("Timeout")), ms) as unknown as number
}),
]).finally(() => clearTimeout(timer))
}
export class CharaDevice { export class CharaDevice {
private port!: SerialPort private port!: SerialPort
private reader!: ReadableStreamDefaultReader<string> private reader!: ReadableStreamDefaultReader<string>
@@ -124,15 +134,25 @@ export class CharaDevice {
} }
private async internalRead() { private async internalRead() {
const {value} = await this.reader.read() try {
serialLog.update(it => { const {value} = await timeout(this.reader.read(), 5000)
it.push({ serialLog.update(it => {
type: "output", it.push({
value: value!, type: "output",
value: value!,
})
return it
}) })
return it return value!
}) } catch (e) {
return value! serialLog.update(it => {
it.push({
type: "output",
value: `${e}`,
})
return it
})
}
} }
/** /**
@@ -169,31 +189,32 @@ export class CharaDevice {
} }
const send = this.internalSend.bind(this) const send = this.internalSend.bind(this)
const read = this.internalRead.bind(this) const read = this.internalRead.bind(this)
const exec = new Promise<T>(async resolve => { let resolveLock: (result: true) => void
let result!: T this.lock = new Promise<true>(resolve => {
try { resolveLock = resolve
if (this.suspendDebounceId) {
clearTimeout(this.suspendDebounceId)
} else {
await this.wake()
}
result = await callback(send, read)
} finally {
delete this.lock
this.suspendDebounceId = setTimeout(() => {
// cannot be locked here as all the code until clearTimeout is sync
console.assert(this.lock === undefined)
this.lock = this.suspend().then(() => {
delete this.lock
delete this.suspendDebounceId
return true
})
}, this.suspendDebounce) as any
resolve(result)
}
}) })
this.lock = exec.then(() => true) let result!: T
return exec try {
if (this.suspendDebounceId) {
clearTimeout(this.suspendDebounceId)
} else {
await this.wake()
}
result = await callback(send, read)
} finally {
delete this.lock
this.suspendDebounceId = setTimeout(() => {
// cannot be locked here as all the code until clearTimeout is sync
console.assert(this.lock === undefined)
this.lock = this.suspend().then(() => {
delete this.lock
delete this.suspendDebounceId
return true
})
}, this.suspendDebounce) as any
resolveLock!(true)
return result
}
} }
/** /**

View File

@@ -1,20 +1,25 @@
export class SemVer { export class SemVer {
major: number major = 0
minor: number minor = 0
patch: number patch = 0
preRelease?: string preRelease?: string
meta?: string meta?: string
constructor(versionString: string) { constructor(versionString: string) {
const [, major, minor, patch, preRelease, meta] = const result =
/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+))?$/.exec( /^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+))?$/.exec(
versionString, versionString,
)! )
this.major = Number.parseInt(major) if (!result) {
this.minor = Number.parseInt(minor) console.error("Invalid version string:", versionString)
this.patch = Number.parseInt(patch) } else {
if (preRelease) this.preRelease = preRelease const [, major, minor, patch, preRelease, meta] = result
if (meta) this.meta = meta this.major = Number.parseInt(major)
this.minor = Number.parseInt(minor)
this.patch = Number.parseInt(patch)
if (preRelease) this.preRelease = preRelease
if (meta) this.meta = meta
}
} }
toString() { toString() {

View File

@@ -69,10 +69,6 @@
$: chordActions = chord?.actions.slice(chord.actions.lastIndexOf(0) + 1).toSorted(compare) $: chordActions = chord?.actions.slice(chord.actions.lastIndexOf(0) + 1).toSorted(compare)
$: compoundIndices = chord?.actions.slice(0, chord.actions.indexOf(0)) $: compoundIndices = chord?.actions.slice(0, chord.actions.indexOf(0))
$: {
console.log(chord?.actions, chordActions, compoundIndices)
}
</script> </script>
<button <button