design patterns – Dynamic abilities of objects during state registration

j & # 39; I not classes that extend from a state class, the object of the state class is to handle the state of extended classes. For each class, we must save it in the database, delete it and select all the data in order to restore the classes at the same time that we stopped (in case of system failure or shutdown ).

For example:

We have TransactionEntry that extends from State each time we process a transaction, we insert it into the database and when the processing is complete, we delete it. In case our system suddenly screams, we need to retrieve all transaction objects (which have not been processed correctly) from the database in our system transaction list in order to continue processing them.

Each entry has a another way to recover (the way we to select data from the database to add it to the system list) and some of them have the possibility to update data in the database.

For example:

FeedbackEntry can do anything TransactionEntry can do, but retrieves data from the database by state and updates the current return status.
Returns have a status, such as current or delayed, so we want to be able to retrieve all comments in progress (or delayed). Because comments have a state and the state sometimes changes (during processing time), we need the ability to update the status in the database.

So FeedbackEntry can do anything that TransactionEntry can do, but the way we retrieve the data is different and, as the feedback can change state, we need to allow the update request.

Until now, we discovered that we had to insert, delete and recover (by selection) in our entries. The difference lies in how we recover them and in the capabilities associated with each channel.

In addition, we want to add more capabilities to certain inputs. Some of them need to be able to try again in case of exception or in case of problem.

For example:

OverrideEntry can do anything FeedbackEntry can do (recovery by state, update, insert, select, delete) and the ability to update the number of retries.
OverrideEntry has logic that, in case of exception, must continue to be processed 3/4 times. So, for each retry time, we need to update the retry counter in the database.

If I understand correctly, OverrideEntry must be able to insert, delete, select, recover by state, update the state and update the number of attempts.

How can I see the implementation?

I see an abstract class called State:

abstract class public state implements Stateable {
// An object of connection to the database

@Override
public void insert (input T) {
// insert an entry in the database
}

@Override
public void remove (input T) {
// delete an entry from the database
}

@Override
public list select (string query) {
// select all data by query
// (this request is flexible in order to serve the types of recovery)
return null;
}
}

Stable interface:

public interface {
empty insertion (T input);
cancel delete (entry T);
listing select (string query);
}

They expose the basic capabilities of insertion, selection and deletion.

From now on, each entry will implement a Recoverable or RecoverableByState:

public recoverable interface stretches {
void recover (Addable director);
}

public interface RecoverableByState stretches {
void recover (Addable manager, int state);
void updateState (T input, int state);
}

Addable is an interface that allows us to add the recovered data to our list:

public interface Addable {
empty add (T entry);
}

All the logic of the entries is in the classes of the manager. Each manager manages the logic of the input, for example:

Public class TransactionManager implements Addable {

Private list of paintings transaction;
void checkTransaction (TransactionEntry entry) {
// ... logical

// In other entries, their manager can change things on the entry
// we need to save this change to the database, like state (from deferred to active)
// or the number of attempts to update or something like that
// we need the ability to update the fields we need:
// overrideState.updateRetryCount (overrideEntry, 3); // will update the number of attempts of overrideEntry to 3
// or overrideState.recover (new OverrideManager (), State.running)
}

void closeTransaction (TransactionEntry input) {
// Remove from the state
// state.remove (entry)
transaction.remove (entry);
}

@Override
public void add (TransactionEntry entry) {
// Insert an entry to indicate
// state.insert (entry)
transaction.add (input);
}
}

Now, for each entry to implement more capabilities, we will create and implement an interface such as:

public retryable interface {
PostgresConnection () connection;

default void updateRetryCount (T entry, int retryCount) {
String query = "update st_statements set retry = {0} where id = {1}";
{0} -> retryCount
{1} -> entry.getID ()
this.postgresConnection.execute (query);
}
}

Example of entries:

A basic entry, contains all the common fields of the entries:

public abstract class StateEntry {
// will have all the common fields of the entries
// like guid, record_creation_time, entry_name ...
}

On TransactionEntry we need a simple recovery without special abilities

Public class TransactionEntry extended StateEntry {
@JsonProperty ("TransactionID")
private String transactionId;

@JsonProperty ("NumOfEntitiesOnTransaction")
private int entitiesOnTransaction;

@JsonProperty ("CreationTime")
private Instant creationTime;

// Ctor
}

On FeedbackEntry, we must recover by state and also update the status

Public class FeedbackEntry extend StateEntry {

@JsonProperty ("Host")
private channel host;

@JsonProperty ("Feedback")
private return JsonNode;

@JsonProperty ("SendingTime")
Private instant sending;

@JsonProperty ("StateType")
private StateType stateType;

// Ctor
}

On OverrideEntry we have to recover by state and

Public class OverrideEntry extends StateEntry {
@JsonProperty ("Message")
private channel message;

@JsonProperty ("StartProcessingTime")
private Instant startProcessingTime;

@JsonProperty ("RetryCount")
private int retryCount;

@JsonProperty ("StateType")
private StateType stateType;

// Ctor

}

What does it look like in the database?

I see only one table, called entrées_état in which each field in StateEntry (the base class from which all the entries extend) is a column and another column of type Json that contains the entry itself after the serialization. Object to Json.

My question

Does it ring and you're fine?

I want to be able to easily create states such as:

Statable transactionState = StateFactory.createInstance (StateType.Recover);

Statable feedbackState = StateFactory.createInstance (StateType.RecoveryByState);

Statable overrideState = StateFactory.createInstance (StateType.RecoveryByState, StateType.Retry);

I mean, I want to create a plant that will create the right mix of state capabilities as I go. I do not think this is possible in the way that I want to implement, so I will be happy to hear your opinions, maybe all the way I think is wrong.
I think of a solution for 3 days and I can not have a good one.

Thank you all for your time and help.

Ben