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

[WIP] New storage using Time Series Server #96

Open
wants to merge 62 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
6165f6c
Init timeseries server-based storage
bhorvilleur-artelys Apr 23, 2021
07feb06
Create AFS storage using TimeSeriesServer (WIP)
bhorvilleur-artelys May 6, 2021
8fd48e4
Add time series server project to master pom
armic-artelys May 6, 2021
6afa4f8
Test TimeSeriesServerAppStorage with a MapDB implementation for gener…
bhorvilleur-artelys May 10, 2021
b99902e
Bugfixes on create and search time series methods:
bhorvilleur-artelys May 11, 2021
c355abc
TimeSeriesServerAppStorage : add publish timeseries method
bhorvilleur-artelys May 11, 2021
554d157
Bugfix call publish timeseries method
bhorvilleur-artelys May 11, 2021
b05fe4c
TimeSeriesServerAppStorage : add fetch timeseries method
bhorvilleur-artelys May 11, 2021
79c809c
Adapt AbstractAppStorageTest to storages which do not handle chunk co…
bhorvilleur-artelys May 18, 2021
8028d83
Specialize TimeSeriesServer in Double time series
bhorvilleur-artelys May 18, 2021
b79dbd4
Merge remote-tracking branch 'origin/draft_ts_server' into draft_ts_s…
armic-artelys May 25, 2021
0bde97f
Checkstyle fix
bhorvilleur-artelys May 26, 2021
5f718f1
AFS time series server : customize the "AFS" app
bhorvilleur-artelys May 26, 2021
2ad5175
Merge remote-tracking branch 'origin/draft_ts_server' into draft_ts_s…
armic-artelys May 27, 2021
99d825f
Code style fixes
armic-artelys Jun 1, 2021
59828bb
Create a special module for timeseries config services
armic-artelys Jun 1, 2021
4c08ce7
Initialization for TS server app file system configuration components
armic-artelys Jun 1, 2021
0908732
Add unit tests to TS server config components
armic-artelys Jun 1, 2021
d7bd572
Setup a conf.yaml file for tests
armic-artelys Jun 1, 2021
d0c65b7
Rework ts server storage classes to setup the modules separation (sto…
armic-artelys Jun 1, 2021
b819782
Add new module in parent pom
armic-artelys Jun 1, 2021
e99a63e
Rework mapdb app file system configuration to allow delegate provider…
armic-artelys Jun 1, 2021
c0895f5
Add support for String time series in time series server AppStorage
armic-artelys Jun 17, 2021
4c55a33
Fix code to match powsybl standards
armic-artelys Jun 18, 2021
3c876f0
Fix checkstyle + remove missing dependency
pl-buiquang Jul 7, 2021
3439ca7
Prepare release v3.4.0
Nov 16, 2020
a8a7bbe
Prepare next release v3.5.0
Nov 16, 2020
fe303a1
Remove ifnotexist when inserting node_data_name (#65)
pl-buiquang Jan 15, 2021
150b2df
Use java 11 for sonar analysis (#70)
pl-buiquang Feb 8, 2021
97a8ffd
Springboot based implementation of AFS backend (#63)
sylvlecl Feb 18, 2021
6f73aa1
Back to springfox v2.9.2, v2.10.5 is broken (#76)
sylvlecl Feb 19, 2021
789b69a
Release v3.5.0
sylvlecl Mar 2, 2021
540d534
Prepare next release v3.6.0
sylvlecl Mar 2, 2021
5847cbc
[Iissue-78] Add NetworkListener on virtual case (#79)
marifunf Apr 16, 2021
8a603cc
Init timeseries server-based storage
bhorvilleur-artelys Apr 23, 2021
e3e2453
Create AFS storage using TimeSeriesServer (WIP)
bhorvilleur-artelys May 6, 2021
328c1c4
Add time series server project to master pom
armic-artelys May 6, 2021
3fa9d97
Test TimeSeriesServerAppStorage with a MapDB implementation for gener…
bhorvilleur-artelys May 10, 2021
fd0c955
Bugfixes on create and search time series methods:
bhorvilleur-artelys May 11, 2021
95ce4ba
TimeSeriesServerAppStorage : add publish timeseries method
bhorvilleur-artelys May 11, 2021
e47ffba
Bugfix call publish timeseries method
bhorvilleur-artelys May 11, 2021
715ba5f
TimeSeriesServerAppStorage : add fetch timeseries method
bhorvilleur-artelys May 11, 2021
7ce55d7
Adapt AbstractAppStorageTest to storages which do not handle chunk co…
bhorvilleur-artelys May 18, 2021
30f47ee
Specialize TimeSeriesServer in Double time series
bhorvilleur-artelys May 18, 2021
f09a560
Checkstyle fix
bhorvilleur-artelys May 26, 2021
b738bff
AFS time series server : customize the "AFS" app
bhorvilleur-artelys May 26, 2021
d3cd820
Code style fixes
armic-artelys Jun 1, 2021
955ead9
Create a special module for timeseries config services
armic-artelys Jun 1, 2021
5b63954
Initialization for TS server app file system configuration components
armic-artelys Jun 1, 2021
99c6152
Add unit tests to TS server config components
armic-artelys Jun 1, 2021
ff05947
Setup a conf.yaml file for tests
armic-artelys Jun 1, 2021
8c0ebb3
Rework ts server storage classes to setup the modules separation (sto…
armic-artelys Jun 1, 2021
63aca9a
Add new module in parent pom
armic-artelys Jun 1, 2021
cc36235
Rework mapdb app file system configuration to allow delegate provider…
armic-artelys Jun 1, 2021
8317832
Add support for String time series in time series server AppStorage
armic-artelys Jun 17, 2021
291b4ef
Fix code to match powsybl standards
armic-artelys Jun 18, 2021
9216dad
Fix checkstyle + remove missing dependency
pl-buiquang Jul 7, 2021
74e501b
Add missing jackson provider dependency
armic-artelys Jul 9, 2021
4d29d36
Fix fetch results subtypes handling in TS storage delegate : retrieve…
armic-artelys Jul 9, 2021
2c449b0
Add missing test dependency : assertj-core
armic-artelys Jul 9, 2021
f4aa998
Merge remote-tracking branch 'origin/draft_ts_server' into draft_ts_s…
bhorvilleur-artelys Jul 21, 2021
91d6495
TimeSeriesDAO now trigger IOException when failing to publish data
armic-artelys Jul 29, 2021
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
Expand Up @@ -22,7 +22,7 @@ public class CassandraAppStorageTest extends AbstractAppStorageTest {
public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet("afs.cql", CassandraConstants.AFS_KEYSPACE), null, 20000L);

@Override
protected AppStorage createStorage() {
public AppStorage createStorage() {
return new CassandraAppStorage("test", () -> new CassandraTestContext(cassandraCQLUnit),
new CassandraAppStorageConfig(), new InMemoryEventsBus());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.powsybl.afs.AfsException;
import com.powsybl.afs.storage.AbstractAppFileSystemConfig;
import com.powsybl.commons.config.ModuleConfig;
import com.powsybl.commons.config.PlatformConfig;

import java.nio.file.Files;
Expand All @@ -31,30 +32,32 @@ public static List<MapDbAppFileSystemConfig> load() {
public static List<MapDbAppFileSystemConfig> load(PlatformConfig platformConfig) {

return platformConfig.getOptionalModuleConfig("mapdb-app-file-system")
.map(moduleConfig -> {
List<MapDbAppFileSystemConfig> configs = new ArrayList<>();
if (moduleConfig.hasProperty("drive-name")
&& moduleConfig.hasProperty("db-file")) {
String driveName = moduleConfig.getStringProperty("drive-name");
boolean remotelyAccessible = moduleConfig.getBooleanProperty("remotely-accessible", DEFAULT_REMOTELY_ACCESSIBLE);
Path rootDir = moduleConfig.getPathProperty("db-file");
configs.add(new MapDbAppFileSystemConfig(driveName, remotelyAccessible, rootDir));
}
int maxAdditionalDriveCount = moduleConfig.getIntProperty("max-additional-drive-count", 0);
for (int i = 0; i < maxAdditionalDriveCount; i++) {
if (moduleConfig.hasProperty("drive-name-" + i)
&& moduleConfig.hasProperty("db-file-" + i)) {
String driveName = moduleConfig.getStringProperty("drive-name-" + i);
boolean remotelyAccessible = moduleConfig.getBooleanProperty("remotely-accessible-" + i, DEFAULT_REMOTELY_ACCESSIBLE);
Path rootDir = moduleConfig.getPathProperty("db-file-" + i);
configs.add(new MapDbAppFileSystemConfig(driveName, remotelyAccessible, rootDir));
}
}
return configs;
})
.map(MapDbAppFileSystemConfig::load)
.orElse(Collections.emptyList());
}

public static List<MapDbAppFileSystemConfig> load(ModuleConfig moduleConfig) {
List<MapDbAppFileSystemConfig> configs = new ArrayList<>();
if (moduleConfig.hasProperty("drive-name")
&& moduleConfig.hasProperty("db-file")) {
String driveName = moduleConfig.getStringProperty("drive-name");
boolean remotelyAccessible = moduleConfig.getBooleanProperty("remotely-accessible", DEFAULT_REMOTELY_ACCESSIBLE);
Path rootDir = moduleConfig.getPathProperty("db-file");
configs.add(new MapDbAppFileSystemConfig(driveName, remotelyAccessible, rootDir));
}
int maxAdditionalDriveCount = moduleConfig.getIntProperty("max-additional-drive-count", 0);
for (int i = 0; i < maxAdditionalDriveCount; i++) {
if (moduleConfig.hasProperty("drive-name-" + i)
&& moduleConfig.hasProperty("db-file-" + i)) {
String driveName = moduleConfig.getStringProperty("drive-name-" + i);
boolean remotelyAccessible = moduleConfig.getBooleanProperty("remotely-accessible-" + i, DEFAULT_REMOTELY_ACCESSIBLE);
Path rootDir = moduleConfig.getPathProperty("db-file-" + i);
configs.add(new MapDbAppFileSystemConfig(driveName, remotelyAccessible, rootDir));
}
}
return configs;
}

private static Path checkDbFile(Path dbFile) {
Objects.requireNonNull(dbFile);
if (Files.isDirectory(dbFile)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private URI getRestUri() {
}

@Override
protected AppStorage createStorage() {
public AppStorage createStorage() {
URI restUri = getRestUri();
return new RemoteAppStorage(FS_TEST_NAME, restUri, "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,23 @@ public abstract class AbstractAppStorageTest {

protected AppStorage storage;

protected boolean conservesChunks;

protected boolean handlesStringTimeSeries;

protected BlockingQueue<NodeEvent> eventStack;

protected AppStorageListener l = eventList -> eventStack.addAll(eventList.getEvents());

public AbstractAppStorageTest() {
this(true, true);
}

public AbstractAppStorageTest(boolean conservesChunks, boolean handlesStringTimeSeries) {
this.conservesChunks = conservesChunks;
this.handlesStringTimeSeries = handlesStringTimeSeries;
}

protected abstract AppStorage createStorage();

@Before
Expand Down Expand Up @@ -385,8 +398,13 @@ public void test() throws IOException, InterruptedException {
assertTrue(storage.getTimeSeriesMetadata(testData3Info.getId(), Sets.newHashSet("ts1")).isEmpty());

// 14) add data to double time series
storage.addDoubleTimeSeriesData(testData2Info.getId(), 0, "ts1", Arrays.asList(new UncompressedDoubleDataChunk(2, new double[] {1d, 2d}),
new UncompressedDoubleDataChunk(5, new double[] {3d})));
if (conservesChunks) {
storage.addDoubleTimeSeriesData(testData2Info.getId(), 0, "ts1", Arrays.asList(new UncompressedDoubleDataChunk(2, new double[] {1d, 2d}),
new UncompressedDoubleDataChunk(5, new double[] {3d})));
} else {
storage.addDoubleTimeSeriesData(testData2Info.getId(), 0, "ts1", Arrays.asList(new UncompressedDoubleDataChunk(0, new double[] {1d, 2d, 3d})));
}

storage.flush();

// check event
Expand All @@ -399,52 +417,58 @@ public void test() throws IOException, InterruptedException {
// check double time series data query
Map<String, List<DoubleDataChunk>> doubleTimeSeriesData = storage.getDoubleTimeSeriesData(testData2Info.getId(), Sets.newHashSet("ts1"), 0);
assertEquals(1, doubleTimeSeriesData.size());
assertEquals(Arrays.asList(new UncompressedDoubleDataChunk(2, new double[] {1d, 2d}),
new UncompressedDoubleDataChunk(5, new double[] {3d})),
doubleTimeSeriesData.get("ts1"));
if (conservesChunks) {
assertEquals(Arrays.asList(new UncompressedDoubleDataChunk(2, new double[] {1d, 2d}),
new UncompressedDoubleDataChunk(5, new double[] {3d})),
doubleTimeSeriesData.get("ts1"));
} else {
assertEquals(Arrays.asList(new UncompressedDoubleDataChunk(0, new double[]{1d, 2d, 3d})), doubleTimeSeriesData.get("ts1"));
}
assertTrue(storage.getDoubleTimeSeriesData(testData3Info.getId(), Sets.newHashSet("ts1"), 0).isEmpty());

// 15) create a second string time series
TimeSeriesMetadata metadata2 = new TimeSeriesMetadata("ts2",
TimeSeriesDataType.STRING,
ImmutableMap.of(),
RegularTimeSeriesIndex.create(Interval.parse("2015-01-01T00:00:00Z/2015-01-01T01:15:00Z"),
Duration.ofMinutes(15)));
storage.createTimeSeries(testData2Info.getId(), metadata2);
storage.flush();

// check event
assertEventStack(new TimeSeriesCreated(testData2Info.getId(), "ts2"));

// check string time series query
assertEquals(Sets.newHashSet("ts1", "ts2"), storage.getTimeSeriesNames(testData2Info.getId()));
metadataList = storage.getTimeSeriesMetadata(testData2Info.getId(), Sets.newHashSet("ts1"));
assertEquals(1, metadataList.size());

// 16) add data to double time series
storage.addStringTimeSeriesData(testData2Info.getId(), 0, "ts2", Arrays.asList(new UncompressedStringDataChunk(2, new String[] {"a", "b"}),
new UncompressedStringDataChunk(5, new String[] {"c"})));
storage.flush();

// check event
assertEventStack(new TimeSeriesDataUpdated(testData2Info.getId(), "ts2"));

// check string time series data query
Map<String, List<StringDataChunk>> stringTimeSeriesData = storage.getStringTimeSeriesData(testData2Info.getId(), Sets.newHashSet("ts2"), 0);
assertEquals(1, stringTimeSeriesData.size());
assertEquals(Arrays.asList(new UncompressedStringDataChunk(2, new String[] {"a", "b"}),
new UncompressedStringDataChunk(5, new String[] {"c"})),
stringTimeSeriesData.get("ts2"));

// 17) clear time series
storage.clearTimeSeries(testData2Info.getId());
storage.flush();

// check event
assertEventStack(new TimeSeriesCleared(testData2Info.getId()));

// check there is no more time series
assertTrue(storage.getTimeSeriesNames(testData2Info.getId()).isEmpty());
if (handlesStringTimeSeries) {
TimeSeriesMetadata metadata2 = new TimeSeriesMetadata("ts2",
TimeSeriesDataType.STRING,
ImmutableMap.of(),
RegularTimeSeriesIndex.create(Interval.parse("2015-01-01T00:00:00Z/2015-01-01T01:15:00Z"),
Duration.ofMinutes(15)));
storage.createTimeSeries(testData2Info.getId(), metadata2);
storage.flush();

// check event
assertEventStack(new TimeSeriesCreated(testData2Info.getId(), "ts2"));

// check string time series query
assertEquals(Sets.newHashSet("ts1", "ts2"), storage.getTimeSeriesNames(testData2Info.getId()));
metadataList = storage.getTimeSeriesMetadata(testData2Info.getId(), Sets.newHashSet("ts1"));
assertEquals(1, metadataList.size());

// 16) add data to double time series
storage.addStringTimeSeriesData(testData2Info.getId(), 0, "ts2", Arrays.asList(new UncompressedStringDataChunk(2, new String[] {"a", "b"}),
new UncompressedStringDataChunk(5, new String[] {"c"})));
storage.flush();

// check event
assertEventStack(new TimeSeriesDataUpdated(testData2Info.getId(), "ts2"));

// check string time series data query
Map<String, List<StringDataChunk>> stringTimeSeriesData = storage.getStringTimeSeriesData(testData2Info.getId(), Sets.newHashSet("ts2"), 0);
assertEquals(1, stringTimeSeriesData.size());
assertEquals(Arrays.asList(new UncompressedStringDataChunk(2, new String[] {"a", "b"}),
new UncompressedStringDataChunk(5, new String[] {"c"})),
stringTimeSeriesData.get("ts2"));

// 17) clear time series
storage.clearTimeSeries(testData2Info.getId());
storage.flush();

// check event
assertEventStack(new TimeSeriesCleared(testData2Info.getId()));

// check there is no more time series
assertTrue(storage.getTimeSeriesNames(testData2Info.getId()).isEmpty());
}

// 18) change parent test
NodeInfo folder1Info = storage.createNode(rootFolderInfo.getId(), "test1", FOLDER_PSEUDO_CLASS, "", 0, new NodeGenericMetadata());
Expand Down
97 changes: 97 additions & 0 deletions afs-timeseries-server-storage/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright (c) 2017, RTE (http://www.rte-france.com)
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<project.version>3.6.0-SNAPSHOT</project.version>
<jackson.version>2.12.1</jackson.version>
<time-series-server.version>0.0.1-SNAPSHOT</time-series-server.version>
</properties>

<parent>
<artifactId>powsybl-afs</artifactId>
<groupId>com.powsybl</groupId>
<version>3.6.0-SNAPSHOT</version>
</parent>

<artifactId>powsybl-afs-timeseries-server-storage</artifactId>
<name>AFS time series server filesystem storage implementations</name>
<description>An AFS time series provider based on time series server</description>

<dependencies>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-afs-storage-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-time-series-server-interfaces</artifactId>
<version>${time-series-server.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>provided</scope>
</dependency>

<!-- tests -->
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-afs-mapdb-storage</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-afs-storage-api</artifactId>
<version>3.6.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>5.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
</dependencies>
</project>
Loading