From d91266fdba793cdd7e6f31fb8e033871b1d82cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Francoeur?= Date: Sun, 13 Jul 2025 10:51:53 -0400 Subject: [PATCH] make TursoDBFactory thread-safe --- .../java/tech/turso/core/TursoDBFactory.java | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/bindings/java/src/main/java/tech/turso/core/TursoDBFactory.java b/bindings/java/src/main/java/tech/turso/core/TursoDBFactory.java index 9bd1201b1..2787da78b 100644 --- a/bindings/java/src/main/java/tech/turso/core/TursoDBFactory.java +++ b/bindings/java/src/main/java/tech/turso/core/TursoDBFactory.java @@ -3,6 +3,7 @@ package tech.turso.core; import java.sql.SQLException; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; /** * Factory class for managing and creating instances of {@link TursoDB}. This class ensures that @@ -13,6 +14,8 @@ public final class TursoDBFactory { private static final ConcurrentHashMap databaseHolder = new ConcurrentHashMap<>(); + private TursoDBFactory() {} + /** * If a database with the same URL already exists, it returns the existing instance. Otherwise, it * creates a new instance and stores it in the database holder. @@ -26,24 +29,42 @@ public final class TursoDBFactory { */ public static TursoDB open(String url, String filePath, Properties properties) throws SQLException { - if (databaseHolder.containsKey(url)) { - return databaseHolder.get(url); - } - if (filePath.isEmpty()) { throw new IllegalArgumentException("filePath should not be empty"); } - final TursoDB database; + TursoDB.load(); + try { - TursoDB.load(); - database = TursoDB.create(url, filePath); + return databaseHolder.computeIfAbsent( + url, + (Sneaky) + u -> { + TursoDB tursoDB = TursoDB.create(u, filePath); + tursoDB.open(0); + return tursoDB; + }); } catch (Exception e) { throw new SQLException("Error opening connection", e); } + } - database.open(0); - databaseHolder.put(url, database); - return database; + private interface Sneaky extends Function { + + T applySneakily(S s) throws E; + + @Override + default T apply(S s) { + try { + return applySneakily(s); + } catch (Exception e) { + throw sneakyThrow(e); + } + } + + @SuppressWarnings("unchecked") + static T sneakyThrow(Exception e) throws T { + throw (T) e; + } } }