Scala service for factorial processing with three modes:
- Kafka consumer/producer: consumes
factorial.tasks, produces tofactorial.results. - HTTP server: consumes JSON and responds with factorial results.
- Console mode: reads numbers from stdin, writes results to
out.txtasynchronously.
- Clone repo into a sibling folder of PRAssign (for Go/Kafka stack):
git clone https://github.com/UsatovPavel/AsyncFactorial.git cd AsyncFactorial - Create
.env:# HTTP сервис Scala SERVER_HOST=0.0.0.0 SERVER_PORT=8080 SERVER_PARALLELISM=4 # empty => use availableProcessors # Kafka service KAFKA_BOOTSTRAP_SERVERS=kafka1:9092,kafka2:9092,kafka3:9092 KAFKA_GROUP_ID=asyncfactorial-consumer KAFKA_INPUT_TOPIC=factorial.tasks KAFKA_OUTPUT_TOPIC=factorial.results CONSUMER_REPLICAS=4 KAFKA_EXPOSE_PORT=9092 # for local-kafka profile only
- Run Kafka consumer (needs Go/Kafka network
prassign_default):(readsmake service
.env, scales consumer toCONSUMER_REPLICAS).
- Kafka service: IOApp
KafkaConsumerTask, consumesfactorial.tasks, publishesfactorial.results. Config via env/application.conf. - Console:
- IOApp
Taskparses integers from stdin untilexit, runs factorials concurrently (non-blocking input), appends results toout.txt(order not guaranteed), logs parse errors. - Two modes:
waitAll=truewaits for all tasks on exit;waitAll=falsecancels unfinished work and stops cleanly. - Built on cats-effect fibers with Supervisor (lightweight, easy to spawn).
- IOApp
- HTTP:
POST /factorial(Tapir + Vert.x), body = JSON array of Int, optional headerX-Job-Id(if missing, generated). Swagger:/docs
- Language: Scala 2.13
- Concurrency/Streams: cats-effect 3, fs2
- Kafka: fs2-kafka
- HTTP: tapir
- JSON: circe
- Test: scalatest (with cats-effect)
- Build tools: Docker Compose (external
prassign_default), Makefile
- Defaults in
application.conf(server.*,kafka.*). - Runtime overrides via env (
SERVER_*,KAFKA_*,CONSUMER_REPLICAS,KAFKA_EXPOSE_PORT).
- Kafka consumer:
make service(requires.env, usesKAFKA_BOOTSTRAP_SERVERS,CONSUMER_REPLICAS). - Local single-broker profile (optional):
docker compose --profile local-kafka up. - HTTP mode (if needed):
docker compose --profile http up app(expects envSERVER_*).
make test- Console pipeline: TaskSpec checks input/parse/write, waitAll true/false, performance
- Writer: NumberWriterSpec — verifies how the writer logs parse errors and normal results, and that it stops cleanly on Shutdown
- Core: FactorialAccumulatorSpec covers factorial on valid/invalid inputs and parse errors.
- HTTP: smoke/bulk/invalid-json/parallel/big-job-id specs for POST /factorial
- Compose
networks.defaultis externalprassign_defaultto talk to Go/Kafka stack.