Skip to content

Replace concurrent-ruby with async#17

Closed
henrikbjorn wants to merge 11 commits into
masterfrom
replace-concurrent-ruby-with-async
Closed

Replace concurrent-ruby with async#17
henrikbjorn wants to merge 11 commits into
masterfrom
replace-concurrent-ruby-with-async

Conversation

@henrikbjorn

Copy link
Copy Markdown
Member

Summary

  • Replace concurrent-ruby dependency with async (> 2.0), io-endpoint (> 0.13), and io-stream (~> 0.11) from the socketry ecosystem
  • Connection reader thread becomes an Async task — no more IO.select polling or command queue
  • Commands write directly to the stream and wait on Async::Condition for responses
  • Call state waits (wait_for_answer, wait_for_bridge, wait_for_end) use Async::Variable instead of Concurrent::CountDownLatch
  • All Mutex usage removed — cooperative fiber scheduling eliminates race conditions
  • Scenario#run wraps in Sync for a transparent async reactor during tests
  • Net result: -541 lines, +495 lines across 12 files

What was replaced

Before After
Thread.new { reader_loop } Async { reader_loop }
Queue + Concurrent::IVar Direct write + Async::Condition
IO.select polling (0.1s timeout) Fiber yields on blocking reads
Mutex (connection, client, events, call) Removed (cooperative scheduling)
Concurrent::CountDownLatch Async::Variable
Concurrent::Map Plain Hash
Concurrent::Event Async::Variable
Concurrent::ScheduledTask Async { sleep(n); block.call }

@henrikbjorn henrikbjorn self-assigned this Feb 24, 2026
@henrikbjorn henrikbjorn requested a review from c960657 February 24, 2026 09:58
@henrikbjorn henrikbjorn force-pushed the replace-concurrent-ruby-with-async branch 4 times, most recently from fba2fe5 to 9c7e74c Compare February 24, 2026 10:41
@henrikbjorn henrikbjorn reopened this Feb 24, 2026
Switch from threads + concurrent-ruby primitives to the socketry async
ecosystem (async, io-endpoint, io-stream) for simpler, cooperative
fiber-based concurrency.

Key changes:
- Reader thread replaced by an Async task (no IO.select polling)
- Concurrent::IVar/Queue command pipeline replaced by direct writes +
  Async::Condition signals
- Concurrent::CountDownLatch replaced by Async::Variable for call
  state waits
- All Mutex usage removed (cooperative scheduling eliminates races)
- Concurrent::Map replaced by plain Hash
- Scenario#run wraps in Sync for transparent async reactor
Add Dockerfile and docker-compose.yml for FreeSWITCH, passing
SignalWire repo credentials via environment variables. Update CI
to build from secrets and gitignore .env for local use.
Use custom Dockerfile with SignalWire repo credentials instead of the
public image, while keeping existing volumes and healthcheck.
@henrikbjorn henrikbjorn force-pushed the replace-concurrent-ruby-with-async branch from 6db2668 to 55b1471 Compare February 24, 2026 13:10
The vanilla config tries to load dozens of modules not installed in our
image, causing CRIT errors. Mount a minimal modules.conf.xml that only
loads what the integration tests need.
- Move call and scenario tests to test/scenarios/ with _scenario suffix
- Add scenario_helper.rb for scenario test configuration
- Add Sync wrapper to ESL connection/client integration tests to
  prevent fiber leaks between test runs
- Add separate CI jobs for integration and scenario tests
- Add rake scenarios task
Remove custom Dockerfile and modules.conf.xml in favour of the
stable third-party image. Drop FS_REPO secrets from CI.
@henrikbjorn henrikbjorn deleted the replace-concurrent-ruby-with-async branch February 27, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant