Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/hazae41/piscine

Create async pools with automatic retry
https://github.com/hazae41/piscine

Last synced: 3 months ago
JSON representation

Create async pools with automatic retry

Awesome Lists containing this project

README

        

![piscine](https://user-images.githubusercontent.com/4405263/225078829-f9cbc271-1740-44b8-929c-802d0929fa5c.png)

Create async pools with automatic retry

```bash
npm i @hazae41/piscine
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/piscine)

## Features

### Current features
- 100% TypeScript and ESM
- No external dependency
- Simple API
- Automatic retry
- Get a fast random value using Math's PRNG
- Get a secure random value using WebCrypto's CSPRNG

## Usage

### WebSockets

Create a pool of WebSockets

```tsx
import "@hazae41/symbol-dispose-polyfill";

import "@hazae41/disposable-stack-polyfill";

import { Disposer } from "@hazae41/disposer"
import { Box } from "@hazae41/box"
import { Pool } from "@hazae41/piscine"
import { Future } from "@hazae41/future"

async function openOrThrow(socket: WebSocket, signal: AbortSignal) {
using stack = new DisposableStack()

const future = new Future()

const onOpen = () => future.resolve()
const onError = () => future.reject(new Error("Errored"))
const onAbort = () => future.reject(new Error("Aborted"))

socket.addEventListener("open", onOpen, { passive: true })
stack.defer(() => socket.removeEventListener("open", onOpen))

socket.addEventListener("error", onError, { passive: true })
stack.defer(() => socket.removeEventListener("error", onError))

signal.addEventListener("abort", onAbort, { passive: true })
stack.defer(() => signal.removeEventListener("abort", onAbort))

return await future.promise
}

const pool = new Pool>(async ({ pool, index, signal }) => {
using stack = new Box(new DisposableStack())

const raw = new WebSocket(`/api`)
await waitOrThrow(raw, signal)

const socket = new Disposer(raw, () => raw.close())

const box = new Box(socket)
stack.getOrThrow().use(box)

const onClose = () => pool.restart(index)

raw.addEventListener("close", onClose, { passive: true })
stack.getOrThrow().defer(() => raw.removeEventListener("close", onClose))

const unstack = stack.unwrapOrThrow()

return new Disposer(box, () => unstack.dispose())
})
```

Start 5 of them

```tsx
for (let i = 0; i < 5; i++)
pool.start(i)
```

You can get the second one

```tsx
const socket = await pool.getOrThrow(1)
```

You can get a random one using Math's PRNG

```tsx
const socket = await pool.getRandomOrThrow()

socket.get().send("Hello world")
```

You can get a random one using WebCrypto's CSPRNG

```tsx
const socket = await pool.getCryptoRandomOrThrow()

socket.get().send("Hello world")
```

You can iterate on them

```tsx
for (const socket of pool)
socket.get().send("Hello world")
```

Or grab all of them

```tsx
const sockets = [...pool]
```

You can take a random one from the pool (and restart its index)

```tsx
import { Mutex } from "@hazae41/mutex"

const mutex = new Mutex(pool)

{
using socket = await Pool.takeCryptoRandomOrThrow(mutex)

socket.get().send("Hello world")

// Close socket
}
```