Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Th2-5165] Use cache in BookInfo #253

Merged
merged 38 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c360d21
[TH2-5165] Use cache in BookInfo
Nikita-Smirnov-Exactpro Feb 15, 2024
19638d1
[TH2-5165] Removed old BookInfo constructor
Nikita-Smirnov-Exactpro Feb 19, 2024
66beb2a
[TH2-5165] Corrected according integration tests
Nikita-Smirnov-Exactpro Feb 19, 2024
10c1056
[TH2-5165] bookId, name, start are unique page identifier
Nikita-Smirnov-Exactpro Feb 19, 2024
ad5f947
[TH2-5165] corrected after review
Nikita-Smirnov-Exactpro Feb 19, 2024
4414d01
[TH2-5165] solved todo/fixme
Nikita-Smirnov-Exactpro Feb 19, 2024
44c5582
[TH2-5165] Added book info metrics
Nikita-Smirnov-Exactpro Feb 20, 2024
9191fd2
[TH2-5165] Added Iterator<PageInfo> getPages
Nikita-Smirnov-Exactpro Feb 20, 2024
a8e2c8f
[TH2-5165] corrected after review
Nikita-Smirnov-Exactpro Feb 21, 2024
2f6c263
[TH2-5165] migrated to IteratorPa
Nikita-Smirnov-Exactpro Feb 22, 2024
d50305e
[TH2-5165] refactored after migration
Nikita-Smirnov-Exactpro Feb 22, 2024
2f298c9
[TH2-5165] Revert API methods
Nikita-Smirnov-Exactpro Feb 22, 2024
6ec65e9
[TH2-5165] Added CradleStorage.getBook method
Nikita-Smirnov-Exactpro Feb 23, 2024
fc0c477
[TH2-5165] getPages(start, end, order) can handle start > end case
Nikita-Smirnov-Exactpro Feb 26, 2024
3a6e9be
[TH2-5165] Removed ThreadSafeProvider class
Nikita-Smirnov-Exactpro Feb 26, 2024
b1d9114
[TH2-5165] Corrected java doc in BookInfo
Nikita-Smirnov-Exactpro Feb 26, 2024
8852126
[TH2-5165] Corrected after review
Nikita-Smirnov-Exactpro Feb 26, 2024
1a848c6
[TH2-5165] Corrected after review
Nikita-Smirnov-Exactpro Feb 26, 2024
fc892ce
[TH2-5165] Fixed problem with Instant MIN/MAX conversion problem
Nikita-Smirnov-Exactpro Feb 27, 2024
2262510
[TH2-5165] Corrected book cache behaviour when book has gap
Nikita-Smirnov-Exactpro Feb 28, 2024
9021c09
[TH2-5165] Added testAddPageInTheMiddleOfExist
Nikita-Smirnov-Exactpro Feb 29, 2024
121d11c
[TH2-5165] corrected after review
Nikita-Smirnov-Exactpro Mar 1, 2024
cb0352e
Update cradle-cassandra/src/test/java/com/exactpro/cradle/cassandra/i…
Nikita-Smirnov-Exactpro Mar 1, 2024
6a5a1ad
[TH2-5165] corrected after review
Nikita-Smirnov-Exactpro Mar 1, 2024
77e8734
[TH2-5165] removed java 17 API
Nikita-Smirnov-Exactpro Mar 1, 2024
ebee034
[TH2-5165] corrected book info metrics
Nikita-Smirnov-Exactpro Mar 1, 2024
4ce8946
[TH2-5165] added testAddTheSecondPageBeforeThreshold test
Nikita-Smirnov-Exactpro Mar 4, 2024
4e0ecca
[TH2-5165] added randomAccessDaysInvalidateInterval option
Nikita-Smirnov-Exactpro Mar 4, 2024
c6e2979
[TH2-5165] corrected after review
Nikita-Smirnov-Exactpro Mar 4, 2024
7ecc0ed
[TH2-5165] revert BOOK_LABEL to book
Nikita-Smirnov-Exactpro Mar 5, 2024
0d29959
[TH2-5165] revert logic to skip register load for empty day page inte…
Nikita-Smirnov-Exactpro Mar 5, 2024
b88f91e
[TH2-5165] revert logic to skip register load for empty day page inte…
Nikita-Smirnov-Exactpro Mar 5, 2024
e9b15b6
Merge remote-tracking branch 'origin/dev-version-5' into TH2-5165
Nikita-Smirnov-Exactpro Mar 6, 2024
7f2926b
[TH2-5165] merged with dev-version-5
Nikita-Smirnov-Exactpro Mar 6, 2024
a578802
[TH2-5165] added BookWithoutPageTest
Nikita-Smirnov-Exactpro Mar 6, 2024
31756d3
[TH2-5165] corrected after review
Nikita-Smirnov-Exactpro Mar 6, 2024
ac5ab52
[TH2-5165] Updated github workflow
Nikita-Smirnov-Exactpro Mar 6, 2024
afe632e
[TH2-5165] Updated github workflow
Nikita-Smirnov-Exactpro Mar 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
name: Build and publish dev-release Java distributions to sonatype.
name: Build and publish dev release jar to sonatype repository

on:
push:
tags:
- \d+.\d+.\d+-dev
on: workflow_dispatch

jobs:
build:
uses: th2-net/.github/.github/workflows/compound-java.yml@main
with:
build-target: 'Sonatype'
runsOn: ubuntu-latest
devRelease: true
createTag: true
secrets:
sonatypeUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
sonatypePassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
Expand Down
Nikita-Smirnov-Exactpro marked this conversation as resolved.
Show resolved Hide resolved
Empty file.
Empty file.
19 changes: 0 additions & 19 deletions .github/workflows/dev-java-publish-sonatype.yml

This file was deleted.

26 changes: 26 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: "Run integration tests for cradle API"

on:
push:
branches:
- '*'

jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 'zulu' '11'
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build with Gradle
run: ./gradlew --info clean integrationTest
- uses: actions/upload-artifact@v3
if: failure()
with:
name: integration-test-results
path: build/reports/tests/integrationTest/
41 changes: 0 additions & 41 deletions .github/workflows/java-publish-sonatype.yml

This file was deleted.

19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,25 @@ Events in a batch can have a reference only to the parent of the batch or other

Test events have mandatory parameters that are verified when storing an event. These are: id, name (for non-batch events), start timestamp.

## Metrics

* `cradle_page_cache_size` (type: Gauge, labels: book, cache) - Size of page cache.
* `cradle_page_cache_page_request_total` (type: Counter, labels: book, cache, method) - Page requests number from cache
* `cradle_page_cache_invalidate_total` (type: Counter, labels: book, cache, cause) - Cache invalidates
* `cradle_page_cache_page_loads_total` (type: Summary, labels: book, cache) - Page loads number to cache
* `_count` - loaded page day intervals
* `_sum` - loaded pages

### Labels:
* cache: HOT, RANDOM
* method: GET, NEXT, PREVIOUS, FIND, ITERATE, REFRESH
* cause: EXPLICIT, REPLACED, COLLECTED, EXPIRED, SIZE

## Release notes

### 5.2.0
* Added page cache for each book to avoid memory leak

## Changes

### 5.1.5
Expand Down
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ subprojects {
targetCompatibility = JavaVersion.VERSION_11 //Java version to generate classes for.
compileJava.options.debugOptions.debugLevel = 'source,lines,vars' // Include debug information

dependencies {
implementation 'io.prometheus:simpleclient_dropwizard:0.16.0'
}

jar {
manifest {
attributes(
Expand Down
1 change: 0 additions & 1 deletion cradle-cassandra/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ dependencies {
implementation "com.datastax.oss:java-driver-query-builder"
implementation "com.datastax.oss:java-driver-mapper-processor"
implementation "com.datastax.oss:java-driver-mapper-runtime"
implementation 'io.prometheus:simpleclient_dropwizard:0.16.0'
implementation 'com.google.guava:guava'

// this section is required to bypass failing vulnerability check caused by cassandra driver's transitive dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Exactpro (Exactpro Systems Limited)
* Copyright 2023-2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -73,7 +73,6 @@
import com.exactpro.cradle.cassandra.keyspaces.CradleInfoKeyspaceCreator;
import com.exactpro.cradle.cassandra.metrics.DriverMetrics;
import com.exactpro.cradle.cassandra.resultset.CassandraCradleResultSet;
import com.exactpro.cradle.cassandra.resultset.SessionsStatisticsIteratorProvider;
import com.exactpro.cradle.cassandra.retries.FixedNumberRetryPolicy;
import com.exactpro.cradle.cassandra.retries.PageSizeAdjustingPolicy;
import com.exactpro.cradle.cassandra.retries.SelectExecutionPolicy;
Expand Down Expand Up @@ -128,6 +127,9 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.exactpro.cradle.cassandra.utils.StorageUtils.toLocalDate;
import static com.exactpro.cradle.cassandra.utils.StorageUtils.toLocalTime;

public class CassandraCradleStorage extends CradleStorage
{
private final Logger LOGGER = LoggerFactory.getLogger(CassandraCradleStorage.class);
Expand Down Expand Up @@ -211,7 +213,11 @@ protected void doInit(boolean prepareStorage) throws CradleStorageException
.setTimeout(timeout)
.setPageSize(resultPageSize);
operators = createOperators(connection.getSession(), settings);
bookCache = new ReadThroughBookCache(operators, readAttrs, settings.getSchemaVersion());
bookCache = new ReadThroughBookCache(operators,
readAttrs,
settings.getSchemaVersion(),
settings.getRandomAccessDaysCacheSize(),
settings.getRandomAccessDaysInvalidateInterval());
bookManager = new BookManager(getBookCache(), settings.getBookRefreshIntervalMillis());
bookManager.start();

Expand Down Expand Up @@ -294,12 +300,12 @@ protected void doAddPages(BookId bookId, List<PageInfo> pages, PageInfo lastPage
String bookName = bookId.getName();
for (PageInfo page : pages)
{
String pageName = page.getId().getName();
String pageName = page.getName();
try
{
PageNameEntity nameEntity = new PageNameEntity(bookName, pageName, page.getStarted(), page.getComment(), page.getEnded());
if (!pageNameOp.writeNew(nameEntity, writeAttrs).wasApplied())
throw new IOException("Query to insert page '"+nameEntity.getName()+"' was not applied. Probably, page already exists");
throw new IOException("Query to insert page '"+nameEntity.getName()+"' book '" + bookId.getName() + "' was not applied. Probably, page already exists");
PageEntity entity = new PageEntity(bookName, pageName, page.getStarted(), page.getComment(), page.getEnded(), page.getUpdated());
pageOp.write(entity, writeAttrs);
}
Expand Down Expand Up @@ -943,29 +949,6 @@ protected Counter doGetCount(BookId bookId, EntityType entityType, Interval inte
}
}

private CompletableFuture<CradleResultSet<String>> doGetSessionsAsync(BookId bookId, Interval interval, SessionRecordType recordType) throws CradleStorageException {
String queryInfo = String.format("%s Aliases in book %s from %s to %s",
recordType.name(),
bookId.getName(),
interval.getStart().toString(),
interval.getEnd().toString());

List<FrameInterval> frameIntervals = StorageUtils.sliceInterval(interval);

SessionsStatisticsIteratorProvider iteratorProvider = new SessionsStatisticsIteratorProvider(
queryInfo,
operators,
getBookCache().getBook(bookId),
composingService,
selectExecutor,
readAttrs,
frameIntervals,
recordType);

return iteratorProvider.nextIterator()
.thenApplyAsync(it -> new CassandraCradleResultSet<>(it, iteratorProvider));
}

@Override
protected CompletableFuture<CradleResultSet<String>> doGetSessionAliasesAsync(BookId bookId, Interval interval) throws CradleStorageException {
String queryInfo = String.format("Session Aliases in book %s from pages that fall within %s to %s",
Expand Down Expand Up @@ -1311,8 +1294,8 @@ protected void removeTestEventData(PageId pageId) {

protected void removePageData(PageInfo pageInfo) throws CradleStorageException {

String book = pageInfo.getId().getBookId().getName();
String page = pageInfo.getId().getName();
String book = pageInfo.getBookName();
String page = pageInfo.getName();

// remove sessions
operators.getPageSessionsOperator().remove(book, page, writeAttrs);
Expand Down Expand Up @@ -1371,23 +1354,25 @@ private void removeEntityStatistics(PageId pageId) {

@Override
protected CompletableFuture<Iterator<PageInfo>> doGetPagesAsync (BookId bookId, Interval interval) {
Instant start = interval.getStart();
Instant end = interval.getEnd();
String queryInfo = String.format(
"Getting pages for book %s between %s - %s ",
bookId.getName(),
interval.getStart(),
interval.getEnd());
start,
end);

PageEntity startPage = operators.getPageOperator()
.getPageForLessOrEqual(
bookId.getName(),
LocalDate.ofInstant(interval.getStart(), TIMEZONE_OFFSET),
LocalTime.ofInstant(interval.getStart(), TIMEZONE_OFFSET),
toLocalDate(start),
toLocalTime(start),
readAttrs).one();

LocalDate startDate = startPage == null ? LocalDate.MIN : startPage.getStartDate();
LocalTime startTime = startPage == null ? LocalTime.MIN : startPage.getStartTime();
LocalDate endDate = LocalDate.ofInstant(interval.getEnd(), TIMEZONE_OFFSET);
LocalTime endTime = LocalTime.ofInstant(interval.getEnd(), TIMEZONE_OFFSET);
LocalDate endDate = toLocalDate(end);
LocalTime endTime = toLocalTime(end);

return operators.getPageOperator().getPagesForInterval(
bookId.getName(),
Expand All @@ -1408,16 +1393,15 @@ protected CompletableFuture<Iterator<PageInfo>> doGetPagesAsync (BookId bookId,

@Override
protected Iterator<PageInfo> doGetPages(BookId bookId, Interval interval) throws CradleStorageException {
String queryInfo = String.format(
"Getting pages for book %s between %s - %s ",
bookId.getName(),
interval.getStart(),
interval.getEnd());

try {
return doGetPagesAsync(bookId, interval).get();
} catch (InterruptedException | ExecutionException e) {
throw new CradleStorageException("Error while " + queryInfo, e);
String error = String.format(
"Error while Getting pages for book %s between %s - %s ",
bookId.getName(),
interval.getStart(),
interval.getEnd());
throw new CradleStorageException(error, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2023 Exactpro (Exactpro Systems Limited)
* Copyright 2020-2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,6 +33,9 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class CassandraStorageSettings extends CoreStorageSettings {
public static final String SCHEMA_VERSION = "5.3.0";
public static final int RANDOM_ACCESS_DAYS_CACHE_SIZE = 10;
/** One day in milliseconds */
public static final long RANDOM_ACCESS_DAYS_CACHE_INVALIDATE_INTERVAL = 24 * 60 * 60 * 1_000;

public static final CassandraConsistencyLevel DEFAULT_CONSISTENCY_LEVEL = CassandraConsistencyLevel.LOCAL_QUORUM;
public static final int DEFAULT_KEYSPACE_REPL_FACTOR = 1;
Expand All @@ -53,9 +56,13 @@ public class CassandraStorageSettings extends CoreStorageSettings {
public static final long DEFAULT_TIMEOUT = 5000;
public static final CompressionType DEFAULT_COMPRESSION_TYPE = CompressionType.ZLIB;

//we need to use Instant.EPOCH instead of Instant.MIN.
//when cassandra driver tries to convert Instant.MIN to milliseconds using toEpochMilli() it causes long overflow.
public static final Instant MIN_EPOCH_INSTANT = Instant.EPOCH;
//we need to use Instant.ofEpochMilli(Long.MAX_VALUE) instead of Instant.MAX.
//when cassandra driver tries to convert Instant.MAX to milliseconds using toEpochMilli() it causes long overflow.
public static final Instant DEFAULT_PAGE_REMOVE_TIME = Instant.ofEpochMilli(Long.MAX_VALUE);
public static final Instant MAX_EPOCH_INSTANT = Instant.ofEpochMilli(Long.MAX_VALUE);
public static final Instant DEFAULT_PAGE_REMOVE_TIME = MAX_EPOCH_INSTANT;

@JsonIgnore
private NetworkTopologyStrategy networkTopologyStrategy;
Expand All @@ -66,6 +73,8 @@ public class CassandraStorageSettings extends CoreStorageSettings {
private CassandraConsistencyLevel readConsistencyLevel = DEFAULT_CONSISTENCY_LEVEL;
private String keyspace;
private String schemaVersion = SCHEMA_VERSION;
private int randomAccessDaysCacheSize = RANDOM_ACCESS_DAYS_CACHE_SIZE;
private long randomAccessDaysInvalidateInterval = RANDOM_ACCESS_DAYS_CACHE_INVALIDATE_INTERVAL;
private int keyspaceReplicationFactor = DEFAULT_KEYSPACE_REPL_FACTOR;

private int maxParallelQueries = DEFAULT_MAX_PARALLEL_QUERIES; // FIXME: remove
Expand Down Expand Up @@ -122,6 +131,8 @@ public CassandraStorageSettings(CassandraStorageSettings settings) {

this.keyspace = settings.getKeyspace();
this.schemaVersion = settings.getSchemaVersion();
this.randomAccessDaysCacheSize = settings.getRandomAccessDaysCacheSize();
this.randomAccessDaysInvalidateInterval = settings.getRandomAccessDaysInvalidateInterval();

this.keyspaceReplicationFactor = settings.getKeyspaceReplicationFactor();
this.maxParallelQueries = settings.getMaxParallelQueries();
Expand Down Expand Up @@ -196,6 +207,14 @@ public String getSchemaVersion() {
return schemaVersion;
}

public int getRandomAccessDaysCacheSize() {
return randomAccessDaysCacheSize;
}

public long getRandomAccessDaysInvalidateInterval() {
return randomAccessDaysInvalidateInterval;
}

public int getKeyspaceReplicationFactor() {
return keyspaceReplicationFactor;
}
Expand Down Expand Up @@ -386,6 +405,8 @@ public String toString() {
", readConsistencyLevel=" + readConsistencyLevel +
", keyspace='" + keyspace + '\'' +
", schemaVersion='" + schemaVersion + '\'' +
", randomAccessDaysCacheSize='" + randomAccessDaysCacheSize + '\'' +
", randomAccessDaysInvalidateInterval='" + randomAccessDaysInvalidateInterval + '\'' +
", keyspaceReplicationFactor=" + keyspaceReplicationFactor +
", maxParallelQueries=" + maxParallelQueries +
", resultPageSize=" + resultPageSize +
Expand Down
Loading
Loading