Fix some memory leaks, add executor.load and some utils
This commit is contained in:
+2
-1
@@ -48,6 +48,7 @@
|
|||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"isomorphic-ws": "^5.0.0",
|
"isomorphic-ws": "^5.0.0",
|
||||||
"nostr-tools": "^1.15.0",
|
"nostr-tools": "^1.15.0",
|
||||||
"npm-run-all": "^4.1.5"
|
"npm-run-all": "^4.1.5",
|
||||||
|
"ws": "^8.14.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,5 +108,7 @@ export class Connection extends Emitter {
|
|||||||
destroy() {
|
destroy() {
|
||||||
this.socket.disconnect()
|
this.socket.disconnect()
|
||||||
this.removeAllListeners()
|
this.removeAllListeners()
|
||||||
|
this.sendQueue.stop()
|
||||||
|
this.receiveQueue.stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ export type Target = Emitter & {
|
|||||||
|
|
||||||
type EventCallback = (url: string, event: Event) => void
|
type EventCallback = (url: string, event: Event) => void
|
||||||
type EoseCallback = (url: string) => void
|
type EoseCallback = (url: string) => void
|
||||||
|
type CloseCallback = () => void
|
||||||
type AuthCallback = (url: string, challenge: string) => void
|
type AuthCallback = (url: string, challenge: string) => void
|
||||||
type OkCallback = (url: string, id: string, ...extra: any[]) => void
|
type OkCallback = (url: string, id: string, ...extra: any[]) => void
|
||||||
type ErrorCallback = (url: string, id: string, ...extra: any[]) => void
|
type ErrorCallback = (url: string, id: string, ...extra: any[]) => void
|
||||||
type CountCallback = (url: string, ...extra: any[]) => void
|
type CountCallback = (url: string, ...extra: any[]) => void
|
||||||
type SubscribeOpts = {onEvent?: EventCallback, onEose?: EoseCallback}
|
type SubscribeOpts = {onEvent?: EventCallback, onEose?: EoseCallback}
|
||||||
|
type LoadOpts = SubscribeOpts & {timeout?: number, onClose?: CloseCallback}
|
||||||
type PublishOpts = {verb: string, onOk: OkCallback, onError: ErrorCallback}
|
type PublishOpts = {verb: string, onOk: OkCallback, onError: ErrorCallback}
|
||||||
type CountOpts = {onCount: CountCallback}
|
type CountOpts = {onCount: CountCallback}
|
||||||
type AuthOpts = {onAuth: AuthCallback, onOk: OkCallback}
|
type AuthOpts = {onAuth: AuthCallback, onOk: OkCallback}
|
||||||
@@ -95,4 +97,29 @@ export class Executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load(filters: Filter[], {timeout = 30_000, onEvent, onEose, onClose}: LoadOpts) {
|
||||||
|
const eose = new Set()
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
onClose?.()
|
||||||
|
sub.unsubscribe()
|
||||||
|
clearTimeout(handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handle = setTimeout(close, timeout)
|
||||||
|
|
||||||
|
const sub = this.subscribe(filters, {
|
||||||
|
onEvent,
|
||||||
|
onEose: (url: string) => {
|
||||||
|
onEose?.(url)
|
||||||
|
eose.add(url)
|
||||||
|
|
||||||
|
if (eose.size === this.target.connections.length) {
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export * from "./Connection"
|
|||||||
export * from "./ConnectionMeta"
|
export * from "./ConnectionMeta"
|
||||||
export * from "./Executor"
|
export * from "./Executor"
|
||||||
export * from "./Pool"
|
export * from "./Pool"
|
||||||
|
export * from "./util/nostr"
|
||||||
export * from "./util/Deferred"
|
export * from "./util/Deferred"
|
||||||
export * from "./util/Emitter"
|
export * from "./util/Emitter"
|
||||||
export * from "./util/Queue"
|
export * from "./util/Queue"
|
||||||
|
|||||||
@@ -50,4 +50,8 @@ export class Queue {
|
|||||||
|
|
||||||
this.timeout = setTimeout(() => this.doWork(), 100) as NodeJS.Timeout
|
this.timeout = setTimeout(() => this.doWork(), 100) as NodeJS.Timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-7
@@ -23,6 +23,7 @@ export class Socket {
|
|||||||
url: string
|
url: string
|
||||||
ws?: WebSocket
|
ws?: WebSocket
|
||||||
ready: Deferred<void>
|
ready: Deferred<void>
|
||||||
|
failedToConnect = false
|
||||||
|
|
||||||
constructor(url: string, readonly opts: SocketOpts) {
|
constructor(url: string, readonly opts: SocketOpts) {
|
||||||
this.url = url
|
this.url = url
|
||||||
@@ -39,7 +40,7 @@ export class Socket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isPending() {
|
isPending() {
|
||||||
return !this.ws
|
return !this.ws && !this.failedToConnect
|
||||||
}
|
}
|
||||||
|
|
||||||
isConnecting() {
|
isConnecting() {
|
||||||
@@ -70,7 +71,10 @@ export class Socket {
|
|||||||
onClose = () => {
|
onClose = () => {
|
||||||
this.ready.reject()
|
this.ready.reject()
|
||||||
this.opts.onClose()
|
this.opts.onClose()
|
||||||
this._close()
|
|
||||||
|
if (this.ws) {
|
||||||
|
this._close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onError = () => {
|
onError = () => {
|
||||||
@@ -100,11 +104,15 @@ export class Socket {
|
|||||||
throw new Error(`Already attempted connection for ${this.url}`)
|
throw new Error(`Already attempted connection for ${this.url}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ws = new WebSocket(this.url)
|
try {
|
||||||
this.ws.onopen = this.onOpen
|
this.ws = new WebSocket(this.url)
|
||||||
this.ws.onclose = this.onClose
|
this.ws.onopen = this.onOpen
|
||||||
this.ws.onerror = this.onError
|
this.ws.onclose = this.onClose
|
||||||
this.ws.onmessage = this.onMessage
|
this.ws.onerror = this.onError
|
||||||
|
this.ws.onmessage = this.onMessage
|
||||||
|
} catch (e) {
|
||||||
|
this.failedToConnect = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
export const stripProto = (url: string) => url.replace(/.*:\/\//, "")
|
||||||
|
|
||||||
|
export const isShareableRelay = (url: string) =>
|
||||||
|
// Is it actually a websocket url
|
||||||
|
url.match(/^wss:\/\/.+/) &&
|
||||||
|
// Sometimes bugs cause multiple relays to get concatenated
|
||||||
|
url.match(/:\/\//g)?.length === 1 &&
|
||||||
|
// It shouldn't have any whitespace
|
||||||
|
!url.match(/\s/) &&
|
||||||
|
// Don't match stuff with a port number
|
||||||
|
!url.slice(6).match(/:\d+/) &&
|
||||||
|
// Don't match raw ip addresses
|
||||||
|
!url.slice(6).match(/\d+\.\d+\.\d+\.\d+/) &&
|
||||||
|
// Skip nostr.wine's virtual relays
|
||||||
|
!url.slice(6).match(/\/npub/)
|
||||||
|
|
||||||
|
export const normalizeRelayUrl = (url: string) => {
|
||||||
|
// If it doesn't start with a compatible protocol, strip the proto and add wss
|
||||||
|
if (!url.match(/^(wss|local):\/\/.+/)) {
|
||||||
|
url = "wss://" + stripProto(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new URL(url).href.replace(/\/+$/, "").toLowerCase()
|
||||||
|
} catch (e) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fromNostrURI = (s: string) => s.replace(/^[\w+]+:\/?\/?/, "")
|
||||||
|
|
||||||
|
export const toNostrURI = (s: string) => `nostr:${s}`
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"extends": "./node_modules/gts/tsconfig-google.json",
|
"extends": "./node_modules/gts/tsconfig-google.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"outDir": "build",
|
"outDir": "dist",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3267,6 +3267,11 @@ write-file-atomic@^4.0.0:
|
|||||||
imurmurhash "^0.1.4"
|
imurmurhash "^0.1.4"
|
||||||
signal-exit "^3.0.7"
|
signal-exit "^3.0.7"
|
||||||
|
|
||||||
|
ws@^8.14.2:
|
||||||
|
version "8.14.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
|
||||||
|
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==
|
||||||
|
|
||||||
y18n@^5.0.5:
|
y18n@^5.0.5:
|
||||||
version "5.0.8"
|
version "5.0.8"
|
||||||
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user