Crypto Market Service is an application that fetches and processes real-time cryptocurrency market data from the CoinGecko API. It uses a clean hexagonal architecture to separate domain logic, application rules, and infrastructure concerns. The service continuously retrieves market data, chart data, and detailed information while dispatching events to downstream systems.
- Market Data Retrieval:
Fetches current market data, chart data, and detailed information for various cryptocurrencies.
- Event Dispatching:
Publishes events with updated market information to an external event dispatcher.
- Fetch Process Management:
Manages periodic fetching using concurrent jobs to continuously update data.
- Hexagonal Architecture:
Clearly separates domain models, application logic, and external adapters.
Crypto Market Service follows a hexagonal architecture:
- Domain Layer:
Contains business models such as Crypto, CryptoChartData, CryptoDetails, and Currency.
- Application Layer:
Implements business rules via services such as FetchCoinMarketDataService and FetchProcessManager.
- Infrastructure Adapter:
Provides adapters for external systems including:
-
HTTP client and API communication via CryptoRepositoryImpl
-
Event dispatching via EventDispatcherAdapter
-
Web server endpoints via WebServer
git clone https://github.com/CryptoMonitorASW-SPE/crypto-market.git
cd crypto-market
Use the Gradle wrapper to build the project. The build configuration is defined in build.gradle.kts.
./gradlew build
This command compiles the code, runs tests, and creates a fat JAR in the build/libs directory.
The application starts a Ktor web server with the main entry point in Main.kt. To run the application:
./gradlew run
The server listens on port 8080 by default.
The web server exposes the following endpoints:
-
POST
/start
Starts the data fetching process for a specified currency (e.g., USD or EUR).- Query Parameter:
currency(defaults toUSD) - Response:
- If the process is already running:
- Returns a status indicating whether data was sent to the event dispatcher or that no data is available.
- If not running:
- Starts the process and returns a "started" status.
- If the process is already running:
- Query Parameter:
-
POST
/stop
Stops the data fetching process for the specified currency.- Query Parameter:
currency(defaults toUSD) - Response: JSON with the status set to "stopped" and the currency code.
- Query Parameter:
-
GET
/status
Returns the running status for all supported currencies as a JSON map. -
GET
/data
Retrieves the latest fetched market data for the given currency.- Responds with HTTP status
204 No Contentif no data is available.
- Responds with HTTP status
-
GET
/health
A simple health-check endpoint returning the server's status. -
GET
/chart/{coinId}/{currency}/{days}
Retrieves chart data for a specific cryptocurrency.- Path Parameters:
coinId: Identifier of the cryptocurrency.currency: The currency code.days: Number of days for chart data.
- Path Parameters:
-
GET
/details/{coinId}
Retrieves detailed information for the specified cryptocurrency.- Path Parameter:
coinId: Identifier of the cryptocurrency.
- Path Parameter:
The project includes unit and integration tests with JUnit5.
To run tests:
./gradlew test
A Dockerfile is provided to build a Docker image of the application.
To build and run the Docker container:
docker build -t cryptomarket .\
docker run -p 8080:8080 cryptomarket
When a push is made to the main branch, an automatic release process is triggered. If a new release is detected, a new Docker package is built and published to GitHub Container Registry.
The CI/CD pipeline ensures that every release includes an updated Docker image. When a new release is created:
-
A Docker image is built.
-
The image is pushed to GHCR.
-
The latest tag is updated.
For each pull request, the following checks are performed:
-
Code Quality and Smell Analysis: The code is analyzed using Detekt to ensure it adheres to Kotlin best practices and to check for code smells.
-
Test Validation: The test suite is executed to verify that all tests pass before merging.
The project uses KtLint for Kotlin code style enforcement.
It is integrated into the commit process using Husky, meaning you cannot commit code that violates style rules.
Commitlint is configured to enforce commit message conventions.
It ensures that all commits follow a standardized format, improving readability and maintainability.