commit 27dd51bc6bfe215a9bb73a8bdef22e202deb227a
parent da423c009c81d1952f49a62cd329388e68d757b8
Author: Kevin Corvisier <git@kevincorvisier.fr>
Date: Thu, 20 Mar 2025 13:45:01 +0900
Have different DBPrintedCard for each finish of scryfall cards
Diffstat:
5 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/database/CardFinish.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/database/CardFinish.java
@@ -0,0 +1,8 @@
+package fr.kevincorvisier.mtg.letstrade.database;
+
+public enum CardFinish
+{
+ NONFOIL,
+ FOIL,
+ ETCHED
+}
diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/database/entities/DBPrintedCard.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/database/entities/DBPrintedCard.java
@@ -2,14 +2,15 @@ package fr.kevincorvisier.mtg.letstrade.database.entities;
import java.util.UUID;
-import org.hibernate.annotations.NaturalId;
-
+import fr.kevincorvisier.mtg.letstrade.database.CardFinish;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
import jakarta.persistence.Version;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
@@ -20,6 +21,7 @@ import lombok.NoArgsConstructor;
import lombok.NonNull;
@Entity(name = "card")
+@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "scryfallId", "finish" }) })
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@@ -40,8 +42,7 @@ public class DBPrintedCard
*/
@NonNull
@NotNull
- @NaturalId
- @Column(updatable = false, nullable = false, unique = true)
+ @Column(updatable = false, nullable = false)
private UUID scryfallId;
@NonNull
@@ -62,6 +63,11 @@ public class DBPrintedCard
@Column(nullable = false)
private String lang;
+ @NonNull
+ @NotNull
+ @Column(nullable = false)
+ private CardFinish finish;
+
/**
* This card’s collector number. Note that collector numbers can contain non-numeric characters, such as letters or ★.
*/
diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/ScryfallRestClient.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/ScryfallRestClient.java
@@ -114,6 +114,9 @@ public class ScryfallRestClient
case "games":
builder.games(readArray(jParser));
break;
+ case "finishes":
+ builder.finishes(readArray(jParser));
+ break;
case "promo_types":
builder.promoTypes(readArray(jParser));
break;
diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/domain/ScryfallCard.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/domain/ScryfallCard.java
@@ -44,6 +44,10 @@ public class ScryfallCard
@NotNull
private Collection<String> games;
+ @NonNull
+ @NotNull
+ private Collection<@NotNull String> finishes;
+
/**
* This card’s set code.
*/
diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/tasks/ScryfallSynchronizationTask.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/tasks/ScryfallSynchronizationTask.java
@@ -7,15 +7,13 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Component;
+import fr.kevincorvisier.mtg.letstrade.database.CardFinish;
import fr.kevincorvisier.mtg.letstrade.database.entities.DBOracleCard;
import fr.kevincorvisier.mtg.letstrade.database.entities.DBOracleCard.DBOracleCardBuilder;
import fr.kevincorvisier.mtg.letstrade.database.entities.DBPrintedCard;
@@ -28,6 +26,7 @@ import fr.kevincorvisier.mtg.letstrade.database.repositories.DBSetRepository;
import fr.kevincorvisier.mtg.letstrade.scryfall.ScryfallRestClient;
import fr.kevincorvisier.mtg.letstrade.scryfall.domain.ScryfallCard;
import jakarta.validation.constraints.NotNull;
+import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -36,7 +35,6 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
public class ScryfallSynchronizationTask
{
- private final ExecutorService executorService = Executors.newSingleThreadExecutor(new CustomizableThreadFactory("scryfall-synchronization-thread-"));
private final DBOracleCardRepository oracleCardRepository;
private final DBSetRepository setRepository;
private final DBCardRepository cardRepository;
@@ -95,11 +93,9 @@ public class ScryfallSynchronizationTask
private void saveCards(final Iterable<ScryfallCard> cards)
{
- executorService.execute(() -> {
- final Map<UUID, DBOracleCard> oracleCards = saveOracleCards(cards);
- final Map<UUID, DBSet> sets = saveSets(cards);
- savePrintedCards(cards, oracleCards, sets);
- });
+ final Map<UUID, DBOracleCard> oracleCards = saveOracleCards(cards);
+ final Map<UUID, DBSet> sets = saveSets(cards);
+ savePrintedCards(cards, oracleCards, sets);
}
@NotNull
@@ -175,9 +171,9 @@ public class ScryfallSynchronizationTask
for (final ScryfallCard card : cards)
scryfallIds.add(card.getId());
- final Map<UUID, DBPrintedCard> existingByScryfallId = new HashMap<>();
+ final Map<DBPrintedCardMergeKey, DBPrintedCard> existingByScryfallId = new HashMap<>();
for (final DBPrintedCard card : cardRepository.findAllByScryfallIdIn(scryfallIds))
- existingByScryfallId.put(card.getScryfallId(), card);
+ existingByScryfallId.put(new DBPrintedCardMergeKey(card), card);
final Collection<DBPrintedCard> toSave = new HashSet<>();
@@ -204,20 +200,43 @@ public class ScryfallSynchronizationTask
continue;
}
- final DBPrintedCard existing = existingByScryfallId.get(card.getId());
- final DBPrintedCardBuilder builder = existing != null ? existing.toBuilder() : DBPrintedCard.builder().scryfallId(card.getId());
+ for (final String finish : card.getFinishes())
+ {
+ final CardFinish finish2 = CardFinish.valueOf(finish.toUpperCase());
- builder.oracleCard(oracleCard);
- builder.lang(card.getLang());
- builder.set(set);
- builder.collectorNumber(card.getCollectorNumber());
- final DBPrintedCard updated = builder.build();
+ final DBPrintedCard existing = existingByScryfallId.get(new DBPrintedCardMergeKey(card, finish2));
+ final DBPrintedCardBuilder builder = existing != null ? existing.toBuilder() : DBPrintedCard.builder().scryfallId(card.getId()).finish(finish2);
- if (existing == null || !existing.equals(updated))
- toSave.add(updated);
+ builder.oracleCard(oracleCard);
+ builder.lang(card.getLang());
+ builder.set(set);
+ builder.collectorNumber(card.getCollectorNumber());
+ final DBPrintedCard updated = builder.build();
+
+ if (existing == null || !existing.equals(updated))
+ toSave.add(updated);
+ }
+ }
+
+ cardRepository.saveAll(toSave);
+ }
+
+ @Data
+ private class DBPrintedCardMergeKey
+ {
+ private final UUID scryfallId;
+ private final CardFinish finish;
+
+ public DBPrintedCardMergeKey(final ScryfallCard card, final CardFinish finish)
+ {
+ this.scryfallId = card.getId();
+ this.finish = finish;
}
- for (final DBPrintedCard card : cardRepository.saveAll(toSave))
- existingByScryfallId.put(card.getScryfallId(), card);
+ public DBPrintedCardMergeKey(final DBPrintedCard card)
+ {
+ this.scryfallId = card.getScryfallId();
+ this.finish = card.getFinish();
+ }
}
}