Saving an article blocked on 21 translation calls

FixKBService
Shipped
September 2, 2026 at 2:17 AM UTC
Author
Kamo
Commit
0459b9a

@Async was inert. **************** called translateArticle on the same bean, so the call went straight to this and never reached the proxy that makes it asynchronous. The annotation was right there in the file, which is why nobody caught it by reading. What that cost: every article save ran 21 sequential HTTP calls to the translation service -- one per locale, 120-second read timeout each -- before the response reached the author's editor. A healthy translation service made it merely slow. A sick one made saving an article take the better part of an hour. Found by an import that hung on its first article. The work moves to KbArticleTranslator, a separate bean, because crossing a bean boundary is what makes the proxy real. Two consequences worth handling in the same change: An executor, because there wasn't one. Spring's fallback starts a fresh thread per task and never reuses it, so genuinely queueing three hundred articles would have answered with three hundred threads all dialling the same service. Now a bounded pool with a bounded queue and CallerRunsPolicy -- rejecting would drop translations silently and an unbounded queue would hide the backlog, whereas caller-runs slows the producer to the rate the pool can sustain. A bound on the retry sweep, which walked every published article and translated inline. Inline that was slow; queued, it would have handed the executor thousands of tasks in one tick. It now queues 25 per sweep and works a backlog down over several.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing