Skip to content

Commit 9696a16

Browse files
authored
Merge branch 'ArcadeData:main' into python-embedded
2 parents 6b72c69 + 732d083 commit 9696a16

46 files changed

Lines changed: 984 additions & 553 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/meterian.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
with:
2727
cli_args: "--report-sarif=report.sarif"
2828
oss: true
29-
- uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3.29.5
29+
- uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v3.29.5
3030
if: success() || failure()
3131
with:
3232
sarif_file: report.sarif

.github/workflows/mvn-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ jobs:
291291
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
292292

293293
- name: Set up Node
294-
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
294+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
295295
with:
296296
node-version: "22"
297297
cache: "npm"
@@ -324,7 +324,7 @@ jobs:
324324
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
325325

326326
- name: Set up Node
327-
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
327+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
328328
with:
329329
node-version: "22"
330330
cache: "npm"

.github/workflows/studio-security-audit.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
4040

4141
- name: "Setup Node.js"
42-
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
42+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
4343
with:
4444
node-version: "18"
4545
cache: "npm"
@@ -166,10 +166,10 @@ jobs:
166166
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
167167

168168
- name: "Initialize CodeQL"
169-
uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3.29.5
169+
uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # v3.29.5
170170
with:
171171
languages: javascript
172172
queries: security-and-quality
173173

174174
- name: "Perform CodeQL Analysis"
175-
uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3.29.5
175+
uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # v3.29.5

e2e-studio/package-lock.json

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e-studio/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"install-browsers": "npx playwright install"
1212
},
1313
"devDependencies": {
14-
"@playwright/test": "^1.56.0",
14+
"@playwright/test": "^1.56.1",
1515
"testcontainers": "^11.7.1",
16-
"@types/node": "^24.7.2",
16+
"@types/node": "^24.8.1",
1717
"typescript": "^5.9.3"
1818
},
1919
"engines": {

engine/src/main/java/com/arcadedb/database/LocalDatabase.java

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,33 @@
8080
import com.arcadedb.utility.MultiIterator;
8181
import com.arcadedb.utility.RWLockContext;
8282

83-
import java.io.*;
84-
import java.nio.channels.*;
85-
import java.nio.file.*;
86-
import java.util.*;
87-
import java.util.concurrent.*;
88-
import java.util.concurrent.atomic.*;
89-
import java.util.concurrent.locks.*;
90-
import java.util.logging.*;
83+
import java.io.File;
84+
import java.io.IOException;
85+
import java.io.RandomAccessFile;
86+
import java.nio.channels.ClosedChannelException;
87+
import java.nio.channels.FileChannel;
88+
import java.nio.channels.FileLock;
89+
import java.nio.file.Files;
90+
import java.nio.file.Path;
91+
import java.util.ArrayList;
92+
import java.util.Arrays;
93+
import java.util.Collection;
94+
import java.util.Collections;
95+
import java.util.HashMap;
96+
import java.util.Iterator;
97+
import java.util.List;
98+
import java.util.Map;
99+
import java.util.Objects;
100+
import java.util.Random;
101+
import java.util.Set;
102+
import java.util.concurrent.Callable;
103+
import java.util.concurrent.ConcurrentHashMap;
104+
import java.util.concurrent.atomic.AtomicBoolean;
105+
import java.util.concurrent.atomic.AtomicLong;
106+
import java.util.concurrent.locks.Lock;
107+
import java.util.concurrent.locks.ReentrantLock;
108+
import java.util.concurrent.locks.ReentrantReadWriteLock;
109+
import java.util.logging.Level;
91110

92111
/**
93112
* Local implementation of {@link Database}. It is based on files opened on the local file system.
@@ -99,9 +118,14 @@
99118
public class LocalDatabase extends RWLockContext implements DatabaseInternal {
100119
public static final int EDGE_LIST_INITIAL_CHUNK_SIZE = 64;
101120
public static final int MAX_RECOMMENDED_EDGE_LIST_CHUNK_SIZE = 8192;
102-
private static final Set<String> SUPPORTED_FILE_EXT = Set.of(Dictionary.DICT_EXT,
103-
LocalBucket.BUCKET_EXT, LSMTreeIndexMutable.NOTUNIQUE_INDEX_EXT, LSMTreeIndexMutable.UNIQUE_INDEX_EXT,
104-
LSMTreeIndexCompacted.NOTUNIQUE_INDEX_EXT, LSMTreeIndexCompacted.UNIQUE_INDEX_EXT, HnswVectorIndex.FILE_EXT);
121+
private static final Set<String> SUPPORTED_FILE_EXT = Set.of(
122+
Dictionary.DICT_EXT,
123+
LocalBucket.BUCKET_EXT,
124+
LSMTreeIndexMutable.NOTUNIQUE_INDEX_EXT,
125+
LSMTreeIndexMutable.UNIQUE_INDEX_EXT,
126+
LSMTreeIndexCompacted.NOTUNIQUE_INDEX_EXT,
127+
LSMTreeIndexCompacted.UNIQUE_INDEX_EXT,
128+
HnswVectorIndex.FILE_EXT);
105129
public final AtomicLong indexCompactions = new AtomicLong();
106130
protected final String name;
107131
protected final ComponentFile.MODE mode;
@@ -538,10 +562,10 @@ public void scanBucket(final String bucketName, final RecordCallback callback, f
538562
public Iterator<Record> iterateType(final String typeName, final boolean polymorphic) {
539563
stats.iterateType.incrementAndGet();
540564

541-
return (Iterator<Record>) executeInReadLock(() -> {
565+
return executeInReadLock(() -> {
542566
checkDatabaseIsOpen();
543-
final DocumentType type = schema.getType(typeName);
544-
final MultiIterator iter = new MultiIterator();
567+
var type = schema.getType(typeName);
568+
var iter = new MultiIterator<Record>();
545569

546570
// SET THE PROFILED LIMITS IF ANY
547571
iter.setLimit(getResultSetLimit());
@@ -1637,12 +1661,7 @@ record = events.onAfterRead(record);
16371661
if (record instanceof Document document) {
16381662
final DocumentType type = document.getType();
16391663
if (type != null) {
1640-
// System.out.println("invokeAfterReadEvents for type = pre");
1641-
1642-
Record record1 = ((RecordEventsRegistry) type.getEvents()).onAfterRead(record);
1643-
// System.out.println("invokeAfterReadEvents for type = after");
1644-
1645-
return record1;
1664+
return ((RecordEventsRegistry) type.getEvents()).onAfterRead(record);
16461665
}
16471666
}
16481667
return record;

engine/src/main/java/com/arcadedb/database/LocalTransactionExplicitLock.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package com.arcadedb.database;
2121

2222
import com.arcadedb.engine.Bucket;
23+
import com.arcadedb.index.IndexInternal;
2324
import com.arcadedb.log.LogManager;
2425
import com.arcadedb.schema.DocumentType;
2526

@@ -61,7 +62,7 @@ public LocalTransactionExplicitLock type(final String typeName) {
6162
// Lock all indexes for this type
6263
filesToLock.addAll(type.getAllIndexes(true).stream()
6364
.flatMap(i -> Arrays.stream(i.getIndexesOnBuckets()))
64-
.map(b -> b.getFileId())
65+
.map(IndexInternal::getFileId)
6566
.toList());
6667

6768
// Lock all currently involved buckets for this type

engine/src/main/java/com/arcadedb/schema/LocalSchema.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,26 @@
5959
import com.arcadedb.serializer.json.JSONObject;
6060
import com.arcadedb.utility.FileUtils;
6161

62-
import java.io.*;
63-
import java.time.*;
64-
import java.util.*;
65-
import java.util.concurrent.*;
66-
import java.util.concurrent.atomic.*;
67-
import java.util.logging.*;
62+
import java.io.File;
63+
import java.io.FileInputStream;
64+
import java.io.FileWriter;
65+
import java.io.IOException;
66+
import java.time.ZoneId;
67+
import java.util.ArrayList;
68+
import java.util.Collection;
69+
import java.util.Collections;
70+
import java.util.Comparator;
71+
import java.util.HashMap;
72+
import java.util.HashSet;
73+
import java.util.Iterator;
74+
import java.util.List;
75+
import java.util.Map;
76+
import java.util.Set;
77+
import java.util.TimeZone;
78+
import java.util.concurrent.Callable;
79+
import java.util.concurrent.ConcurrentHashMap;
80+
import java.util.concurrent.atomic.AtomicLong;
81+
import java.util.logging.Level;
6882

6983
/**
7084
* Local implementation of the database schema.
@@ -1199,6 +1213,7 @@ public synchronized void saveConfiguration() {
11991213
}
12001214

12011215
try {
1216+
LogManager.instance().log(this, Level.INFO, "Saving schema configuration to file - versionSerial = %s ", versionSerial);
12021217
versionSerial.incrementAndGet();
12031218

12041219
update(toJSON());

engine/src/test/java/com/arcadedb/ACIDTransactionTest.java

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.arcadedb.schema.Schema;
3737
import com.arcadedb.schema.Type;
3838
import com.arcadedb.schema.VertexType;
39+
import org.awaitility.Awaitility;
3940
import org.junit.jupiter.api.Tag;
4041
import org.junit.jupiter.api.Test;
4142

@@ -46,6 +47,12 @@
4647
import java.util.Iterator;
4748
import java.util.List;
4849
import java.util.concurrent.Callable;
50+
import java.util.concurrent.ExecutionException;
51+
import java.util.concurrent.ExecutorService;
52+
import java.util.concurrent.Executors;
53+
import java.util.concurrent.Future;
54+
import java.util.concurrent.TimeUnit;
55+
import java.util.concurrent.TimeoutException;
4956
import java.util.concurrent.atomic.AtomicBoolean;
5057
import java.util.concurrent.atomic.AtomicInteger;
5158
import java.util.logging.Level;
@@ -78,13 +85,6 @@ public void testAsyncTX() {
7885

7986
db.async().waitCompletion();
8087

81-
try {
82-
Thread.sleep(500);
83-
} catch (final InterruptedException e) {
84-
Thread.currentThread().interrupt();
85-
// IGNORE IT
86-
}
87-
8888
} catch (final TransactionException e) {
8989
assertThat(e.getCause() instanceof IOException).isTrue();
9090
}
@@ -240,13 +240,6 @@ public Void call() throws IOException {
240240

241241
db.async().waitCompletion();
242242

243-
try {
244-
Thread.sleep(500);
245-
} catch (final InterruptedException e) {
246-
Thread.currentThread().interrupt();
247-
// IGNORE IT
248-
}
249-
250243
assertThat(errors.get()).isEqualTo(1);
251244

252245
} catch (final TransactionException e) {
@@ -486,10 +479,12 @@ public void testExceptionInsideTransaction() {
486479

487480
final int CONCURRENT_THREADS = 4;
488481

489-
// SPAWN ALL THE THREADS
490-
final Thread[] threads = new Thread[CONCURRENT_THREADS];
482+
// SPAWN ALL THE THREADS USING EXECUTORSERVICE
483+
final ExecutorService executorService = Executors.newFixedThreadPool(CONCURRENT_THREADS);
484+
final List<Future<?>> futures = new ArrayList<>();
485+
491486
for (int i = 0; i < CONCURRENT_THREADS; i++) {
492-
threads[i] = new Thread(() -> {
487+
Future<?> future = executorService.submit(() -> {
493488
for (int k = 0; k < TOT; ++k) {
494489
final int id = k;
495490

@@ -512,16 +507,33 @@ public void testExceptionInsideTransaction() {
512507
}
513508

514509
});
515-
threads[i].start();
510+
futures.add(future);
516511
}
517512

518513
// WAIT FOR ALL THE THREADS
519-
for (int i = 0; i < CONCURRENT_THREADS; i++)
514+
for (Future<?> future : futures) {
520515
try {
521-
threads[i].join();
516+
future.get(120, TimeUnit.SECONDS);
522517
} catch (InterruptedException e) {
523-
// IGNORE IT
518+
Thread.currentThread().interrupt();
519+
LogManager.instance().log(this, Level.WARNING, "Thread interrupted while waiting for future", e);
520+
} catch (ExecutionException e) {
521+
LogManager.instance().log(this, Level.WARNING, "Execution exception in future", e);
522+
} catch (TimeoutException e) {
523+
LogManager.instance().log(this, Level.SEVERE, "Future timed out after 120 seconds", e);
524+
future.cancel(true);
524525
}
526+
}
527+
528+
executorService.shutdown();
529+
try {
530+
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
531+
executorService.shutdownNow();
532+
}
533+
} catch (InterruptedException e) {
534+
executorService.shutdownNow();
535+
Thread.currentThread().interrupt();
536+
}
525537

526538
assertThat(database.countType("Node", true)).isEqualTo(1);
527539

0 commit comments

Comments
 (0)