Microservice providing sun ephemeris as a REST endpoint, and the stream of events to Redis channel, published at the time of their occurrence.
- Gradle
- Spring Boot
- Spring Boot Actuator
- Spring Boot Dev Tools
- Spring Boot Admin
- Spring MVC
- Spring Data Redis
- Lombok
- ShedLock
- Resilience4J
- Redis
- Springdoc-OpenAPI
- OpenAPI Generator
- Spock Framework
- WireMock
- Testcontainers and Playtika
- GitHub Actions
- SonarCloud
- Docker
For the full list see the build.gradle.
Design, code structure and naming convention were inspired by:
- Onion / Clean / Hexagonal Architecture
- Domain Driven Design (DDD)
If one wants to read more about combining all these together, here is an interesting article.
Service does not calculate sun ephemeris on its own. Instead, it uses API exposed by Sunrise-Sunset site (kudos for great work!). Client code is generated from specification with OpenAPI Generator. To optimize network traffic and avoid risk of abusing API usage rules, received ephemeris is cached in Redis under a date key.
Please note: Since, it is assumed that location is static configuration and never changes during service lifetime, location is not part of the key.
Each day, shortly after midnight, publish scheduler requests new day ephemeris and schedules tasks that will publish events to Redis channel at the event time. The same data is also available as REST endpoint for interested parties. Following sun ephemeris events are available:
- dawn
- sunrise
- noon
- sunset
- dusk
Please note: Events on Redis channel and REST endpoint have the same structure. It is documented in endpoint OpenAPI specification.
Since there might be more than one instance of the service (e.g. due to HA requirements), publishers try to acquire a
lock and only winner publishes event. Following diagram presents events publishing sequence:
Sunrise-Sunset is an external endpoint that might be down at any time without a notice. In order to mitigate this risk,
service retries calls with an exponentially growing backoff time. Since data is requested shortly after midnight,
it should give enough time for Sunrise-Sunset site to recover before first ephemeris event (dawn) time. However, if
outage continues, publish scheduler uses previous day ephemeris which should be accurate enough as a replacement.
Following diagram presents fallback sequence:
Service is distributed as a Docker image. The latest version (including release candidates) is available in
DockerHub under tag
mwierzchowski/sun-ephemeris:latest
.
In order to start container, at minimum following environment variables have to be provided:
location.latitude
andlocation.longitude
- coordinates for ephemeris calculationspring.redis.host
- Redis host name (assuming default port is used)
All properties are listed in application.yml.
Please note: Service depends on Spring Boot autoconfiguration feature that may be configured with additional properties.
Project development requires following software being installed on a developer's machine:
Tool | Version | Comment |
---|---|---|
Git | latest |
|
JDK | 15 |
AdoptOpenJDK is recommended |
IDE | latest |
IntelliJ IDEA is recommended |
Docker Desktop | 2.4 or newer |
Please note: Project does not depend on IntelliJ IDEA specific features. Feel free to use Eclipse or Notepad instead :)
Optionally, consider installing IDE plugins that improve development experience. Recommended plugins should have versions available for most popular IDEs (IntelliJ links below):
Plugin | Comment |
---|---|
Lombok | Support for Lombok generated code |
MapStruct | Support for MapStruct generated code |
Docker | Support for docker-compose (handy when starting application locally) |
SonarLint | Quality feedback on the fly |
PlantUML | Helps writing diagrams with PlantUML |
Please note: Without some of these plugins, IDEs may highlight references to generated code (e.g. Lombok properties or MapStruct mappers) as errors. It is annoying but do not affect building or running application.
Development environment is provided as a code by Docker Compose. It may be controlled with standard docker commands or using Gradle tasks:
composeUp
- starts dev-env as Docker Compose services (waits until services are up and running)composeDown
- stops dev-env (all the data is wiped, including database content)
For example, following command starts dev-env:
./gradlew composeUp
Once started, following services are available:
Service | URL | Credentials |
---|---|---|
Spring Boot Admin | http://localhost:82 | admin / admin |
Swagger UI | http://localhost:83/swagger | n/a |
Redis | http://localhost:6379 | n/a |
Project build is powered by Gradle wrapper with additional plugins (e.g. java
, spring-boot
,
docker-compose
). Few most useful build tasks:
clean
- cleans the buildtest
- executes unit and integration testsbuild
- builds the application (and executes tests)
For example, following command runs a clean build:
./gradlew clean build
Service, as a regular Spring Boot application may be started locally by running main application class or using Gradle task:
bootRun
- starts application (compiles and builds code if needed)
Since application to start requires development tools to be up and running, one may combine Gradle tasks to launch complete development environment with a single command, e.g.:
./gradlew composeUp bootRun
Once started, application listens on http://localhost:8080. Status of the running application can be checked using one of the Actuator endpoints, e.g.:
- http://localhost:8080/actuator/info - general info
- http://localhost:8080/actuator/health - health status
Please note: Project includes spring-boot-devtools "that can make the application development experience a little more pleasant", e.g. provides code changes detection and automatic restarts.
This software is released under the MIT Open Source license.