mirror of
https://github.com/supabase/supabase.git
synced 2026-05-08 01:40:13 -04:00
d8f7cc0d57
* o11y: mirror and sanitize breadcrumbs Mirror Sentry breadcrumbs as the basis for our own support logging. Also adds more sanitization to breadcrumbs. * feat(support form): toggle for attaching dashboard logs Add a toggle to the support form when the category is "Dashboard bug", to attach recent dashboard logs. Users can preview the attached logs and opt out. * feat(support links): dedicated support link component Add a new component for support links, which: - Uses the serializer for support link params to ensure serialization/deserialization pairs correctly - Snapshots breadcrumbs so the attached log on the support form will be cut off at the support link click (otherwise we will get support form actions cluttering up the log) * tests(support form): extend timeout on flaky test * Minor clean up * fix(support form): allow url to specifically indicate no specified project * minor nits * Fix tests * Fix tests --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
88 lines
2.0 KiB
TypeScript
88 lines
2.0 KiB
TypeScript
export class RingBuffer<T> {
|
|
private readonly capacity: number
|
|
private readonly buffer: (T | undefined)[]
|
|
private head = 0
|
|
private tail = 0
|
|
private size = 0
|
|
|
|
constructor(capacity: number) {
|
|
if (!Number.isInteger(capacity) || capacity <= 0) {
|
|
throw new Error('RingBuffer capacity must be a positive integer')
|
|
}
|
|
|
|
this.capacity = capacity
|
|
this.buffer = new Array<T | undefined>(capacity).fill(undefined)
|
|
}
|
|
|
|
get length(): number {
|
|
return this.size
|
|
}
|
|
|
|
pushBack(value: T): void {
|
|
this.buffer[this.tail] = value
|
|
|
|
if (this.size === this.capacity) {
|
|
this.head = (this.head + 1) % this.capacity
|
|
} else {
|
|
this.size += 1
|
|
}
|
|
|
|
this.tail = (this.tail + 1) % this.capacity
|
|
}
|
|
|
|
popFront(): T | undefined {
|
|
if (this.size === 0) {
|
|
return undefined
|
|
}
|
|
|
|
const value = this.buffer[this.head]
|
|
this.buffer[this.head] = undefined
|
|
this.head = (this.head + 1) % this.capacity
|
|
this.size -= 1
|
|
|
|
return value
|
|
}
|
|
|
|
popBack(): T | undefined {
|
|
if (this.size === 0) {
|
|
return undefined
|
|
}
|
|
|
|
const index = (this.tail - 1 + this.capacity) % this.capacity
|
|
const value = this.buffer[index]
|
|
this.buffer[index] = undefined
|
|
this.tail = index
|
|
this.size -= 1
|
|
|
|
return value
|
|
}
|
|
|
|
toArray(start?: number, end?: number): T[] {
|
|
const len = this.size
|
|
|
|
let startIndex = start === undefined ? 0 : Math.trunc(start)
|
|
if (startIndex < 0) {
|
|
startIndex = Math.max(len + startIndex, 0)
|
|
} else {
|
|
startIndex = Math.min(startIndex, len)
|
|
}
|
|
|
|
let endIndex = end === undefined ? len : Math.trunc(end)
|
|
if (endIndex < 0) {
|
|
endIndex = Math.max(len + endIndex, 0)
|
|
} else {
|
|
endIndex = Math.min(endIndex, len)
|
|
}
|
|
|
|
const sliceLength = Math.max(endIndex - startIndex, 0)
|
|
const result = new Array<T>(sliceLength)
|
|
|
|
for (let offset = 0; offset < sliceLength; offset += 1) {
|
|
const physicalIndex = (this.head + startIndex + offset) % this.capacity
|
|
result[offset] = this.buffer[physicalIndex] as T
|
|
}
|
|
|
|
return result
|
|
}
|
|
}
|