public Map<ClientPlatform, Map<Semver, ClientRelease>> getClientReleases() {
    return Collections.unmodifiableMap(
        Flux.from(dynamoDbAsyncClient.scanPaginator(ScanRequest.builder()
                    .tableName(tableName)
                    .build())
                .items())
            .mapNotNull(ClientReleases::releaseFromItem)
            .groupBy(ClientRelease::platform)
            .flatMap(groupedFlux -> groupedFlux.collectMap(ClientRelease::version)
                .map(releasesByVersion -> Tuples.of(groupedFlux.key(), releasesByVersion)))
            .collectMap(Tuple2::getT1, Tuple2::getT2)
            .blockOptional()
            .orElseGet(Collections::emptyMap));
  }
@Test
  void getClientReleases() {
    final Instant releaseTimestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS);
    final Instant expiration = releaseTimestamp.plusSeconds(60);

    storeClientRelease("IOS", "1.2.3", releaseTimestamp, expiration);
    storeClientRelease("IOS", "not-a-valid-version", releaseTimestamp, expiration);
    storeClientRelease("ANDROID", "4.5.6", releaseTimestamp, expiration);
    storeClientRelease("UNRECOGNIZED_PLATFORM", "7.8.9", releaseTimestamp, expiration);

    final Map<ClientPlatform, Map<Semver, ClientRelease>> expectedVersions = Map.of(
        ClientPlatform.IOS, Map.of(new Semver("1.2.3"), new ClientRelease(ClientPlatform.IOS, new Semver("1.2.3"), releaseTimestamp, expiration)),
        ClientPlatform.ANDROID, Map.of(new Semver("4.5.6"), new ClientRelease(ClientPlatform.ANDROID, new Semver("4.5.6"), releaseTimestamp, expiration)));

    assertEquals(expectedVersions, clientReleases.getClientReleases());
  }