diff --git a/src/main/docker-compose/jvm.yml b/src/main/docker-compose/jvm.yml index fe2da17..563b008 100644 --- a/src/main/docker-compose/jvm.yml +++ b/src/main/docker-compose/jvm.yml @@ -17,6 +17,10 @@ services: reservations: memory: 128M cpus: "0.3" + redis: + image: redis + networks: + - anyame-consul consul: image: "hashicorp/consul:1.22" command: >- diff --git a/src/main/java/com/backend/unifier/title/model/ContentProviderSource.java b/src/main/java/com/backend/unifier/title/model/ContentProviderSource.java new file mode 100644 index 0000000..01f8bcc --- /dev/null +++ b/src/main/java/com/backend/unifier/title/model/ContentProviderSource.java @@ -0,0 +1,5 @@ +package com.backend.unifier.title.model; + +public enum ContentProviderSource { + KODIK +} diff --git a/src/main/java/com/backend/unifier/title/model/IdentifierPointer.java b/src/main/java/com/backend/unifier/title/model/IdentifierPointer.java deleted file mode 100644 index 72aabc0..0000000 --- a/src/main/java/com/backend/unifier/title/model/IdentifierPointer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.backend.unifier.title.model; - -import java.util.UUID; - -public class IdentifierPointer { - private UUID key; - private ContentIdentifier identifier; - - public IdentifierPointer(UUID key, ContentIdentifier identifier) { - this.key = key; - this.identifier = identifier; - } - - IdentifierPointer() { - } - - public UUID getKey() { - return key; - } - - public ContentIdentifier getIdentifier() { - return identifier; - } - -} diff --git a/src/main/java/com/backend/unifier/title/resource/DetailResource.java b/src/main/java/com/backend/unifier/title/resource/DetailResource.java index 077bc4f..be258d7 100644 --- a/src/main/java/com/backend/unifier/title/resource/DetailResource.java +++ b/src/main/java/com/backend/unifier/title/resource/DetailResource.java @@ -2,15 +2,15 @@ package com.backend.unifier.title.resource; import com.backend.unifier.title.model.ContentDetailEntry; -import io.smallrye.openapi.internal.models.media.Content; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; @Path("/") public class DetailResource { @GET @Path("/detail") - public ContentDetailEntry detail(String id) { + public ContentDetailEntry detail(@QueryParam("id") String id) { return null; } } diff --git a/src/main/java/com/backend/unifier/title/resource/SearchResource.java b/src/main/java/com/backend/unifier/title/resource/SearchResource.java index a8451dd..9e4aa91 100644 --- a/src/main/java/com/backend/unifier/title/resource/SearchResource.java +++ b/src/main/java/com/backend/unifier/title/resource/SearchResource.java @@ -6,7 +6,6 @@ import com.backend.unifier.title.api.KodikSearchService; import com.backend.unifier.title.model.SearchEntries; import com.backend.unifier.title.service.KodikResponseConvertService; -import io.smallrye.mutiny.Uni; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.QueryParam; @@ -24,14 +23,6 @@ public class SearchResource { @GET @Path("/search") - public Uni search(@QueryParam("title") String title) { - return kodikSearchService.searchAsync(title) - .onItem().ifNotNull() - .transformToUni(response -> kodikConvertService.convertAsync(response)); - } - - @GET - @Path("/search-fast") public SearchEntries searchFast(@QueryParam("title") String title) { var result = kodikSearchService.search(title); return kodikConvertService.convert(result); diff --git a/src/main/java/com/backend/unifier/title/service/IdentifierMaskService.java b/src/main/java/com/backend/unifier/title/service/IdentifierMaskService.java new file mode 100644 index 0000000..524daae --- /dev/null +++ b/src/main/java/com/backend/unifier/title/service/IdentifierMaskService.java @@ -0,0 +1,31 @@ +package com.backend.unifier.title.service; + +import java.util.UUID; + +import com.backend.unifier.title.model.ContentIdentifier; +import com.backend.unifier.title.model.ContentProviderSource; + +import io.quarkus.redis.datasource.RedisDataSource; +import io.quarkus.redis.datasource.value.ValueCommands; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class IdentifierMaskService { + private ValueCommands countCommands; + + public IdentifierMaskService(RedisDataSource ds) { + countCommands = ds.value(ContentIdentifier.class); + } + + public UUID createMask(String id, ContentProviderSource source) { + ContentIdentifier contentIdentifier = new ContentIdentifier(source.name(), id); + UUID pointerID = UUID.randomUUID(); + countCommands.set(pointerID.toString(), contentIdentifier); + return pointerID; + } + + public ContentIdentifier realIdentifier(UUID id) { + return countCommands.get(id.toString()); + } + +} diff --git a/src/main/java/com/backend/unifier/title/service/IdentifierPointerService.java b/src/main/java/com/backend/unifier/title/service/IdentifierPointerService.java deleted file mode 100644 index e1c0a16..0000000 --- a/src/main/java/com/backend/unifier/title/service/IdentifierPointerService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.backend.unifier.title.service; - -import com.backend.unifier.title.model.ContentIdentifier; - -import io.quarkus.redis.datasource.RedisDataSource; -import io.quarkus.redis.datasource.value.ValueCommands; -import jakarta.enterprise.context.ApplicationScoped; - -@ApplicationScoped -public class IdentifierPointerService { - private ValueCommands countCommands; - - public IdentifierPointerService(RedisDataSource ds) { - countCommands = ds.value(ContentIdentifier.class); - - } - -} diff --git a/src/main/java/com/backend/unifier/title/service/KodikResponseConvertService.java b/src/main/java/com/backend/unifier/title/service/KodikResponseConvertService.java index 1ad10d4..fbb9b02 100644 --- a/src/main/java/com/backend/unifier/title/service/KodikResponseConvertService.java +++ b/src/main/java/com/backend/unifier/title/service/KodikResponseConvertService.java @@ -1,60 +1,49 @@ package com.backend.unifier.title.service; -import java.util.List; +import java.util.UUID; import org.mapstruct.factory.Mappers; import com.backend.metadata.kodik.api.model.KodikResponse; import com.backend.unifier.title.mapper.KodikResponseMapper; -import com.backend.unifier.title.model.ContentSearchEntry; +import com.backend.unifier.title.model.ContentProviderSource; import com.backend.unifier.title.model.SearchEntries; -import io.smallrye.mutiny.Uni; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class KodikResponseConvertService { private final KodikResponseMapper responseMapper = Mappers.getMapper(KodikResponseMapper.class); - private final PosterUrlValidator posterUrlValidator; private final PosterUrlNormalizer posterUrlNormalizer; + private final IdentifierMaskService identifierMaskService; - public KodikResponseConvertService(PosterUrlValidator posterUrlValidator, PosterUrlNormalizer posterUrlNormalizer) { - this.posterUrlValidator = posterUrlValidator; + public KodikResponseConvertService(PosterUrlNormalizer posterUrlNormalizer, + IdentifierMaskService identifierMaskService) { this.posterUrlNormalizer = posterUrlNormalizer; + this.identifierMaskService = identifierMaskService; } public SearchEntries convert(KodikResponse response) { return convertSimple(response); } - @SuppressWarnings("unchecked") - public Uni convertAsync(KodikResponse response) { - if (response == null || response.results == null) { - return Uni.createFrom().item(new SearchEntries(List.of())); - } - - List> entries = convertSimple(response).result() - .stream() - .map(this::resolveEntryPosters) - .toList(); - - if (entries.isEmpty()) { - return Uni.createFrom().item(new SearchEntries(List.of())); - } - - return Uni.combine().all().unis(entries) - .with(list -> new SearchEntries((List) list)); - } - - private Uni resolveEntryPosters(ContentSearchEntry entry) { - return posterUrlValidator.resolvePosters(entry.posterURLs()) - .map(entry::withPosterURLs) - .onFailure().recoverWithItem(entry); - } - private SearchEntries convertSimple(KodikResponse response) { - return normalizeUrls(responseMapper.toSearchEntries(response)); + SearchEntries withNormalizedUrls = normalizeUrls(responseMapper.toSearchEntries(response)); + SearchEntries result = maskIDs(withNormalizedUrls); + return result; + + } + + private SearchEntries maskIDs(SearchEntries response) { + var normalizedResults = response.result().stream() + .map(r -> { + String originalID = r.id(); + UUID maskedID = identifierMaskService.createMask(originalID, ContentProviderSource.KODIK); + return r.withId(maskedID.toString()); + }) + .toList(); + return response.withResult(normalizedResults); } private SearchEntries normalizeUrls(SearchEntries response) { diff --git a/src/main/java/com/backend/unifier/title/service/PosterUrlValidator.java b/src/main/java/com/backend/unifier/title/service/PosterUrlValidator.java deleted file mode 100644 index d3967e5..0000000 --- a/src/main/java/com/backend/unifier/title/service/PosterUrlValidator.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.backend.unifier.title.service; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import io.smallrye.mutiny.Uni; -import io.vertx.core.Vertx; -import io.vertx.ext.web.client.WebClient; -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class PosterUrlValidator { - - @ConfigProperty(name = "poster.url.timeoutMs", defaultValue = "3000") - long timeoutMs; - - @Inject - Vertx vertx; - - private WebClient webClient; - - @PostConstruct - void init() { - webClient = WebClient.create(vertx); - } - - public Uni> resolvePosters(List urls) { - if (urls == null || urls.isEmpty()) { - return Uni.createFrom().item(List.of()); - } - - return findFirstReachable(urls, 0) - .map(firstIndex -> reorderToFront(urls, firstIndex)); - } - - private Uni findFirstReachable(List urls, int index) { - if (index >= urls.size()) { - return Uni.createFrom().item(-1); - } - return isReachable(urls.get(index)) - .flatMap(ok -> ok ? Uni.createFrom().item(index) : findFirstReachable(urls, index + 1)); - } - - private List reorderToFront(List urls, int firstIndex) { - if (firstIndex <= 0) - return urls; - List reordered = new ArrayList<>(urls); - reordered.add(0, reordered.remove(firstIndex)); - return reordered; - } - - private Uni isReachable(String url) { - if (url == null || url.isEmpty()) { - return Uni.createFrom().item(false); - } - return Uni.createFrom().completionStage( - webClient.headAbs(url).timeout(timeoutMs).send().toCompletionStage()) - .map(response -> response.statusCode() >= 200 && response.statusCode() < 400) - .onFailure().recoverWithItem(false); - } -} diff --git a/src/main/java/com/backend/unifier/title/service/service/PosterUrlNormalizer.java b/src/main/java/com/backend/unifier/title/service/service/PosterUrlNormalizer.java deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 5de40fc..70b71cc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,3 +16,4 @@ quarkus.http.cors.origins=http://localhost:3000 quarkus.http.cors.methods=GET,PUT,POST quarkus.http.cors.access-control-max-age=24H quarkus.http.cors.access-control-allow-credentials=true +quarkus.redis.hosts=redis://redis:6379