1
27

Deno team is joining Cloudflare and will soon stop working on the Deno runtime and Deno Deploy

2
5
3
4
4
2
5
1
Ember 7.3 Released (blog.emberjs.com)
6
6

I made a small rate limiter for JS. It's about 1 KB, has no dependencies and runs on Node, Bun, Deno and Cloudflare Workers.

It uses GCRA, so each key is just one timestamp instead of a counter plus a timer. Nothing runs in the background. Keys you've already seen don't allocate either, since the timestamps live in a Float64Array.

import { limito } from 'limito'

const rl = limito({ limit: 100, window: '1m' })
const wait = rl('user:42') // 0 if allowed, otherwise ms to wait

There's also a Redis version for when you have multiple servers, and small middlewares for Express and Hono.

MIT licensed, still early (0.5). Feedback and bug reports welcome.

7
2
8
2
9
1
Half Past Fetch (blog.gaborkoos.com)
10
3
Your typeof Is Lying to You (blog.gaborkoos.com)
11
1
Ember 7.2 Released (blog.emberjs.com)
12
2
13
4
14
8
15
5

hello

I need to create in javascript something to change a color to transparent, on PNG
I'd like to create a form that, when I post a picture, everything white should be transformed to transparent and generated as a new PNG, however this white is coming from a picture so it won't be exactly white
but contrast are good since this will pictures of text written on a white page
maybe some king of green screen algo

any ideas on how to do that ?

16
13
17
6
18
11
submitted 1 month ago* (last edited 1 month ago) by codeinabox@programming.dev to c/javascript@programming.dev
19
-1
20
3
Your Modules Are Lying to You (blog.gaborkoos.com)
21
5
22
6
submitted 2 months ago* (last edited 2 months ago) by MasterPick520@programming.dev to c/javascript@programming.dev

Most of us implement idempotency the same way the first time. Check whether you've seen the key, and if not, do the work and store the key so the next request knows:

app.post("/charge", async (req, res) => {
  const key = req.get("Idempotency-Key");
  if (await redis.get(key)) { 
      return res.json(JSON.parse(await redis.get(`${key}:result`)));
  }

  const result = await chargeCard(req.body);      // real money leaves here
  await redis.set(key, "done");
  await redis.set(`${key}:result`, JSON.stringify(result));
  res.json(result);
});

It reviews fine. Then two things happen in production.

Two retries arrive at the same moment. Both reach the get before either reaches the set, so both charge the card. A load test finds this one if you go looking.

The process dies after chargeCard and before redis.set. The money moved, the key was never written, and the retry charges again. This one you can't easily reproduce on purpose, and it happens on its own during any deploy.

Fixing the first properly means the check and the write have to be one atomic operation, so exactly one caller wins. That creates the next problem: the winner can die holding the key, so the claim needs a lease that expires. Which creates another: the "dead" worker might just be slow, wake up, and overwrite the real result with its stale one. So the write needs a fencing token that the reclaimer invalidates.

I got tired of rewriting that, so it's a library now:

import express from "express";
import { idempotency } from "idemkit/express";
import { RedisBackend } from "idemkit/redis";

const app = express();
app.use(idempotency({ backend: await RedisBackend.fromUrl(process.env.REDIS_URL) }));

app.post("/charge", async (req, res) => {
  res.status(201).json(await chargeCard(req.body));   // runs once per Idempotency-Key
});

Same thing works for queue consumers (SQS, Kafka, RabbitMQ, BullMQ) and plain function calls. Redis, Postgres, Mongo, DynamoDB or in memory. Zero dependencies, Apache-2.0.

https://github.com/idemkit/idemkit

If you find it useful, a star would be much appreciated.

23
7
Your JSON Is Lying to You (blog.gaborkoos.com)
24
3
25
3
view more: next ›

JavaScript

2830 readers
3 users here now

founded 3 years ago
MODERATORS