This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
Refactor persistence layer. #399
Labels
code-refactoring
The change reduces the cognitive load of the reader of the code and makes adding new changes easier
Comments
yojs
added
the
code-refactoring
The change reduces the cognitive load of the reader of the code and makes adding new changes easier
label
Aug 26, 2020
yojs
added a commit
that referenced
this issue
Sep 1, 2020
Fixes: #399 The persistence layer takes care of durably storing the RCA results (and in future decisions from deciders) and providing them when asked for it. The layer also takes care of periodic file rotations and cleaning up old DB files. Although, it wasn't intended, the _Persistence_ layer is tightly coupled to the _RCA graph_ today. If you look at the `write()` method in `Persistable` interface, you will find this signature: `<T extends ResourceFlowUnit> void write(Node<?> node, T flowUnit) throws SQLException, IOException;` So the Persistable Object knows about the graph node. Therefore, in future as the remediation system evolves and we have components, that are not nodes in the RCA-Graph, we might still want to persist their outputs and this interface can't do that. Therefore, the goal is to make the methods of Persistable generic, so that it can persist any object given to it and be able to read out any object the caller asks for. Say we have to persist this class: ```java Outer.java ________________ class Outer { int x; int y; boolean z; String name; List<T> myList; B b_obj; } ------------------------------------------------------- A.java _______ class B { int x; String y; } ``` when the above code is annotated as: ```java Outer.java ________________ // This will create a table named "Outer" @table class Outer { int x; int y; // Its not annotated as column, therefore, it will not be persisted. boolean z; String name; B b_obj; List<T> myList; // Add a column named x to Outer table. The value stored in the row for that column will be the value of x. @column int getX() { .. } @column int getY() { .. } @column String getName() { .. } // For all fields that are not [primitive types](https://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#isPrimitive()), they will be persisted in their own tables as a new row. The auto-increment ID for this row will be persisted as a value of the column named "__table__B", so that we have a link to the nested element/table from this table. @column B getBObj() {..} // If the Column annotation exists for a collection type, then they will be written to a table of their own. // The name of the table is obtained by calling T.class.getSimpleName(). If all of them evaluates to the same // table name, then they get written to the same table as different rows. And the corresponding Outer table's // column will have a string [<rowId1]>, <rowId2>]. // If `T.class.getSimpleName()` evaluates to different names, then they are linked back in Outer table as // different columns. @column List<T> getMyList() { .. } } ------------------------------------------------------- B.java _______ @table class B { int x; String y; } ``` this creates these set of tables: Here assuming that `getMyList()` returns a list of three elements where ```java for (T in getMyList) { // T.getClass().getSimpleName() returns `T` for two of the objects and `TT` for the third. } ``` Table Outer timestamp|ID|X|Y|Name|__table__BObj|__table__T|__table__TT --|--|--|-|------|--------------|----------------|--- ..|53|1|2|name|34|[23,24]|32 Table B timestamp|ID|X|Y --|--|--|-- ..|34|23|y Table T timestamp|ID| col2| .. --|---|-|-------- ..|23|24|.. ..|24|24|.. Table TT timestamp|ID| col2| .. --|---|-|-------- ..|32|24|.. - The Java code resembles how the tables and nested tables will be laid out. - Because the nested table can be obtained just by reading the column name, someone can write a tool to read the RCAs from the SQLite files. The won't need the java package to figure out the nesting. - If new columns or nestings are added, they can also be added in the DB without schema mismatch. This is because, we create a new SQLite file on each restart of the RCA agent process (on top of periodic file rotations). - The table name and column names are derived from the classname and getter name (methodName with `get` stripped out). This provides a 1-1 mapping from the persistor class and fields to the table name and column names. - Over and above, we are able to persist any Java Object.
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
code-refactoring
The change reduces the cognitive load of the reader of the code and makes adding new changes easier
The persistence layer takes care of durably storing the RCA results (and in future decisions from deciders) and providing them when asked for it. The layer also takes care of periodic file rotations and cleaning up old DB files.
Although, it wasn't intended, the Persistence layer is tightly coupled to the RCA graph today. If you look at the
write()
method inPersistable
interface, you will find this signature:<T extends ResourceFlowUnit> void write(Node<?> node, T flowUnit) throws SQLException, IOException;
Today the persistence layer is very tightly coupled with the RCA graph nodes and flow units and these are the only types that can be persisted today. But in future, as the remediation framework evolves, we will have components, that are not nodes in the RCA-Graph. They can be action suggestions or other information.
Features that should be supported:
Field
reference other user defined Classes.The text was updated successfully, but these errors were encountered: