Skip to content

Intégration des travaux du Projet 8 OpenClassrooms (étapes 2 à 6)#1

Merged
Xajah merged 6 commits into
masterfrom
dev
Jun 5, 2026
Merged

Intégration des travaux du Projet 8 OpenClassrooms (étapes 2 à 6)#1
Xajah merged 6 commits into
masterfrom
dev

Conversation

@Xajah

@Xajah Xajah commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Cette PR intègre dans master l'ensemble des modifications réalisées sur dev
dans le cadre du Projet 8 du parcours Java d'OpenClassrooms.

Commits inclus :

  • fix(rewards): correction du ConcurrentModificationException et du bug
    de logique dans addUserReward, réactivation du test nearAllAttractions
    (étape 2 : concurrence et stabilisation des tests)

  • feat: implémentation de getNearbyAttractions retournant les 5 attractions
    les plus proches via un record AttractionsDto (étape 3)

  • perf: parallélisation des appels gpsUtil et RewardCentral avec des
    ExecutorService dédiés, dimensionnement empirique des pools, sécurisation
    des collections par CopyOnWriteArrayList. Les tests highVolumeTrackLocation
    (100k users) passent en 3 min 23 et highVolumeGetRewards en 1 min 45,
    largement sous les seuils OpenClassrooms (étape 4)

  • ci: ajout du pipeline GitHub Actions (build, test, packaging, artefact
    JAR téléchargeable, déclenchement manuel via workflow_dispatch) (étape 5)

  • docs: ajout du README à la racine (étape 6)

Xajah added 6 commits May 23, 2026 21:30
- RewardsService.calculateRewards : add defensive snapshot of visitedLocations
  to prevent ConcurrentModificationException when the Tracker thread modifies
  the list during iteration.
- User.addUserReward : fix logic bug where String.equals(Attraction) always
  returned false, blocking all reward additions after the first one.
  Replaced filter().count() == 0 with noneMatch (short-circuit + readable).
- TestRewardsService.nearAllAttractions : remove @disabled, the test now passes.

Refs: OpenClassrooms Projet 8 - etape 2 (corriger le code pour valider les tests).
- AttractionsDto (record) : new DTO in dto/ package carrying attraction
  name, lat/long, user lat/long, distance in miles and reward points.
  Java record chosen for immutability and zero boilerplate.
- RewardsService.getRewardPoints : changed from private to package-private,
  parameter changed from User to UUID to avoid coupling with User object.
- TourGuideService.getNearByAttractions : replaced proximity-filter logic
  with a stream sorted by distance (comparingDouble), limited to 5,
  mapped to AttractionsDto. Returns the 5 closest regardless of distance.
- TourGuideController.getNearbyAttractions : updated return type from
  List<Attraction> to List<AttractionsDto>, removed TODO comment.
- TestTourGuideService.getNearbyAttractions : remove @disabled, updated
  return type to List<AttractionsDto>, test now passes (assertEquals 5).

Refs: OpenClassrooms Projet 8 - etape 3 (implémenter le bug des attractions).
…ead pools

- TourGuideService : add a dedicated ExecutorService (pool size 50) for
  I/O-bound parallelization of gpsUtil calls. Expose trackUserLocationAsync
  returning a CompletableFuture<VisitedLocation>. The synchronous
  trackUserLocation is preserved for the REST controllers and the Tracker.
- RewardsService : add a separate ExecutorService (pool size 500) and expose
  calculateRewardsAsync returning a CompletableFuture<Void>. The pool size
  is much larger than TourGuide's because each task contains several nested
  I/O calls (one per nearby attraction).
- Pool sizes determined empirically : TourGuide pool tested at 25/50/100/200/500,
  plateau at 50 (limited by sync calculateRewards inside each task). Rewards
  pool tested at 25 to 1000 in 10 steps, plateau at 500.
- User.visitedLocations and User.userRewards : switched to CopyOnWriteArrayList
  for thread-safety under parallel writes. Profile "many reads, few writes"
  makes this the optimal choice over synchronizedList (which would have
  serialized reads and negated the parallelism benefit).
- @PreDestroy on shutdownExecutor() in both services : clean lifecycle
  management of the thread pools via the Spring container.
- TestPerformance : remove @disabled from both perf tests, set volume to
  100 000 users, use CompletableFuture.allOf().join() to launch and await
  parallel calls, call shutdownExecutor() at the end to free resources.

Profiling before optimization confirmed the program was I/O-bound : the
application threads spent ~100% of their wall-clock time in gpsUtil.sleep
with 0% CPU usage. The optimization targets the wait time, not CPU work --
hence the choice of CompletableFuture + ExecutorService sized generously
beyond the number of cores.

Results : highVolumeTrackLocation passes 100k users in 3m23 (budget 15min,
x4.4 margin), highVolumeGetRewards passes 100k users in 1m45 (budget 20min,
x11.4 margin, down from 17h47 OC baseline). Full mvn test : 11/11 tests pass
in 5m28.

Refs: OpenClassrooms Projet 8 - etape 4 (parallelisation gpsUtil + RewardsCentral).
- .github/workflows/build.yml : new workflow triggered on push to dev/master,
  on pull requests targeting master, and manually via workflow_dispatch.
  Runs on Ubuntu, sets up Java 17 (Temurin) with Maven cache.
- Local JARs installation : the gpsUtil, TripPricer and RewardCentral
  JARs from TourGuide/libs/ are installed into the runner local Maven
  repository before build, since they are not available on Maven Central
  and the CI runner is a clean Ubuntu image.
- Build pipeline split into two distinct steps : mvn test followed by
  mvn package -DskipTests. This gives a granular green/red status in
  the GitHub Actions UI (immediate visual identification of the failing
  phase) without paying the cost of running the perf tests twice.
- The resulting JAR is uploaded as a downloadable artifact named
  tourguide-jar with 30 days retention, fulfilling the OpenClassrooms
  requirement of a downloadable executable artifact at pipeline output.
- The workflow_dispatch trigger allows manual reruns from the GitHub UI
  to regenerate a fresh artifact on demand, without pushing new code.

Refs: OpenClassrooms Projet 8 - etape 5 (pipeline d integration continue).
Add a README at the repository root providing:
- project context (OpenClassrooms Java Path Project 8),
- technical architecture overview with component responsibilities,
- prerequisites, build and run instructions,
- main REST endpoints reference,
- test suite description,
- performance results compared to OpenClassrooms targets,
- CI pipeline description (GitHub Actions workflow),
- repository organisation.

The README serves as the entry point for reviewers arriving on the GitHub
repository and as a quick reference for build and run.

Refs: OpenClassrooms Projet 8 - etape 6 (documentation et soutenance).
@Xajah Xajah merged commit 460c3aa into master Jun 5, 2026
2 checks passed
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