Skip to content

Commit

Permalink
create basic elements for Miroir Action Script (MAS), migrate Tools.s…
Browse files Browse the repository at this point in the history
…ubmit to MAS #28. Use in-memory ExtractorRunner.handleQuery for indexedDb, filesystem and postgres implementations. Some refactorings / renamings around DomainController, PersistenceReduxSaga, PersistenceStoreController, PersistenceStoreControllerManager.
  • Loading branch information
miroir-framework committed Aug 15, 2024
1 parent b377cdd commit 8ee0ebc
Show file tree
Hide file tree
Showing 42 changed files with 959 additions and 561 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
QueryAction,
TransactionalInstanceAction
} from "../1_core/preprocessor-generated/miroirFundamentalType.js";
import { PersistenceInterface } from "../4-services/PersistenceInterface.js";
import { PersistenceStoreLocalOrRemoteInterface } from "../4-services/PersistenceInterface.js";


// #############################################################################################
Expand Down Expand Up @@ -122,6 +122,6 @@ export interface DomainControllerInterface {
// TODO: currentTransaction should not depend on localCache types?! Use DomainActions instead?
currentTransaction(): (TransactionalInstanceAction | ModelAction)[],
currentLocalCacheInfo(): LocalCacheInfo,
getRemoteStore(): PersistenceInterface,
getRemoteStore(): PersistenceStoreLocalOrRemoteInterface,

}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ export type ExtractorRunnerMap<StateType> = AsyncExtractorRunnerMap<StateType> |

// ################################################################################################
export interface PersistenceStoreExtractorRunner {
handleQuery(section: ApplicationSection, query: QueryAction): Promise<ActionReturnType>;
// handleQuery(section: ApplicationSection, query: QueryAction): Promise<ActionReturnType>;
handleQuery(query: QueryAction): Promise<ActionReturnType>;
extractEntityInstance:AsyncExtractorRunner<
ExtractorForSingleObject, any, DomainElementEntityInstanceOrFailed
>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ export default {};
/**
* Decorator to the Redux Store, handing specific Miroir entity slices
*/
export declare interface PersistenceInterface {
export declare interface PersistenceStoreLocalOrRemoteInterface {
handlePersistenceAction(
action: PersistenceAction
): Promise<ActionReturnType>;
}

export interface StoreInterface extends LocalCacheInterface, PersistenceInterface {};
export interface StoreInterface extends LocalCacheInterface, PersistenceStoreLocalOrRemoteInterface {};
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,17 @@ export interface StorageSpaceHandlerInterface {
}

// ###########################################################################################
export interface PersistenceStoreInstanceSectionAbstractInterface {
export interface PersistenceStoreInstanceSectionAbstractInterface extends PersistenceStoreAbstractSectionInterface{
getInstance(parentUuid: string, uuid: string): Promise<ActionEntityInstanceReturnType>;
getInstances(parentUuid: string): Promise<ActionEntityInstanceCollectionReturnType>;
// handleQuery(query: QueryAction): Promise<ActionReturnType>; // TODO: polymorphize function with return type depending on query type?
handleQuery(query: QueryAction): Promise<ActionReturnType>; // TODO: polymorphize function with return type depending on query type?
upsertInstance(parentUuid:string, instance:EntityInstance):Promise<ActionVoidReturnType>;
deleteInstances(parentUuid:string, instances:EntityInstance[]):Promise<ActionVoidReturnType>;
deleteInstance(parentUuid:string, instance:EntityInstance):Promise<ActionVoidReturnType>;
}

// ###########################################################################################
export interface PersistenceStoreEntitySectionAbstractInterface {
export interface PersistenceStoreEntitySectionAbstractInterface extends PersistenceStoreAbstractSectionInterface {
existsEntity(entityUuid:string):boolean;

createEntity(
Expand Down Expand Up @@ -183,9 +183,10 @@ export interface PersistenceStoreControllerInterface
getDataState(): Promise<{ [uuid: string]: EntityInstanceCollection }>; // used only for testing purposes!

// // instance interface differs from the one in PersistenceStoreInstanceSectionAbstractInterface: it has an ApplicationSection as first parameter
handleQuery(section: ApplicationSection, query: QueryAction): Promise<ActionReturnType>;

getInstance(section: ApplicationSection, parentUuid: string, uuid: Uuid): Promise<ActionEntityInstanceReturnType>;
getInstances(section: ApplicationSection, parentUuid: string): Promise<ActionEntityInstanceCollectionReturnType>;
// handleQuery(section: ApplicationSection, query: QueryAction): Promise<ActionReturnType>;
upsertInstance(section: ApplicationSection, instance: EntityInstance): Promise<ActionVoidReturnType>;
deleteInstance(section: ApplicationSection, instance: EntityInstance): Promise<ActionVoidReturnType>;
deleteInstances(section: ApplicationSection, instance: EntityInstance[]): Promise<ActionVoidReturnType>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Uuid } from "../1_core/EntityDefinition.js";
import { ActionReturnType, StoreUnitConfiguration } from "../1_core/preprocessor-generated/miroirFundamentalType.js";
import { DomainControllerInterface } from "../2_domain/DomainControllerInterface.js";
import { LocalCacheInterface } from "./LocalCacheInterface.js";
import { PersistenceInterface } from "./PersistenceInterface.js";
import { PersistenceStoreLocalOrRemoteInterface } from "./PersistenceInterface.js";
import { InitApplicationParameters, PersistenceStoreControllerInterface } from "./PersistenceStoreControllerInterface.js";


Expand All @@ -13,9 +13,9 @@ export interface PersistenceStoreControllerManagerInterface {
): Promise<void>;

// getReduxStore(): LocalCacheInterface;
getPersistenceStore(): PersistenceInterface;
getPersistenceStoreLocalOrRemote(): PersistenceStoreLocalOrRemoteInterface;
getLocalCache(): LocalCacheInterface;
getDomainController(): DomainControllerInterface;
getServerDomainController(): DomainControllerInterface;

getPersistenceStoreControllers(): string[];
getPersistenceStoreController(deploymentUuid: Uuid): PersistenceStoreControllerInterface | undefined;
Expand Down
22 changes: 9 additions & 13 deletions packages/miroir-core/src/3_controllers/DomainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { MiroirContextInterface } from '../0_interfaces/3_controllers/MiroirCont
import {
LocalCacheInterface
} from "../0_interfaces/4-services/LocalCacheInterface.js";
import { PersistenceInterface } from '../0_interfaces/4-services/PersistenceInterface.js';
import { PersistenceStoreLocalOrRemoteInterface } from '../0_interfaces/4-services/PersistenceInterface.js';


import adminConfigurationDeploymentMiroir from "../assets/admin_data/7959d814-400c-4e80-988f-a00fe582ab98/10ff36f2-50a3-48d8-b80f-e48e5d13af8e.json";
Expand Down Expand Up @@ -127,16 +127,17 @@ export class DomainController implements DomainControllerInterface {
private callUtil: CallUtils;

constructor(
private hasDirectAccessToPersistenceStore: boolean,
private domainControllerIsDeployedOn: "server" | "client",
private miroirContext: MiroirContextInterface,
private localCache: LocalCacheInterface,
private persistenceStore: PersistenceInterface, // instance of PersistenceReduxSaga
private persistenceStore: PersistenceStoreLocalOrRemoteInterface, // instance of PersistenceReduxSaga
private endpoint: Endpoint,
) {
this.callUtil = new CallUtils(miroirContext.errorLogService, localCache, persistenceStore);
}

getRemoteStore(): PersistenceInterface {
// TODO: remove? only used in commented code in index.tsx
getRemoteStore(): PersistenceStoreLocalOrRemoteInterface {
return this.persistenceStore;
}
// ##############################################################################################
Expand Down Expand Up @@ -254,12 +255,13 @@ export class DomainController implements DomainControllerInterface {
try {
switch (modelAction.actionName) {
case "remoteLocalCacheRollback": {
if (this.hasDirectAccessToPersistenceStore) {
if (this.domainControllerIsDeployedOn == "server") {
// if the domain controller is deployed on the server, we refresh the local cache from the remote store
log.info("handleModelAction reloading current configuration from local PersistenceStore!");
await this.loadConfigurationFromPersistenceStore(deploymentUuid);
log.info("handleModelAction reloading current configuration from local PersistenceStore DONE!");
} else {
// send action to (remote) persistence action interface handler.
// if the domain controller is deployed on the client, we send the "remoteLocalCacheRollback" action to the server
await this.callUtil.callPersistenceAction(
{}, // context
{}, // context update
Expand Down Expand Up @@ -733,13 +735,7 @@ export class DomainController implements DomainControllerInterface {
JSON.stringify((queryAction as any)["objects"], null, 2)
);

// if (queryAction.query.queryType == "domainModelSingleExtractor" ) {
// // if (["domainModelSingleExtractor","extractorForRecordOfExtractors"].includes(queryAction.query.queryType) ) {
// log.info("handleQuery queryAction", queryAction);
// throw new Error("DomainController handleQuery queryAction not implemented for queryType " + queryAction.query.queryType);
// }

if (this.hasDirectAccessToPersistenceStore) {
if (this.domainControllerIsDeployedOn == "server") {
/**
* we're on the server side. Shall we execute the query on the localCache or on the persistentStore?
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import {
} from "../../0_interfaces/1_core/preprocessor-generated/miroirFundamentalType.js";
import { ErrorLogServiceInterface, MError } from "../../0_interfaces/3_controllers/ErrorLogServiceInterface.js";
import { LocalCacheInterface } from "../../0_interfaces/4-services/LocalCacheInterface.js";
import { PersistenceInterface } from "../../0_interfaces/4-services/PersistenceInterface.js";
import { PersistenceStoreLocalOrRemoteInterface } from "../../0_interfaces/4-services/PersistenceInterface.js";

export class CallUtils {
constructor(
private errorLogService: ErrorLogServiceInterface,
private localCache: LocalCacheInterface,
private persistenceStore: PersistenceInterface
private persistenceStore: PersistenceStoreLocalOrRemoteInterface
) {}

// ######################################################################################
Expand Down
33 changes: 18 additions & 15 deletions packages/miroir-core/src/4_services/PersistenceStoreController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { cleanLevel } from "./constants.js";
import { ACTION_OK } from "../1_core/constants.js";
import entityEntity from "../assets/miroir_model/16dbfe28-e1d7-4f20-9ba4-c1a9873202ad/16dbfe28-e1d7-4f20-9ba4-c1a9873202ad.json";
import entityEntityDefinition from "../assets/miroir_model/16dbfe28-e1d7-4f20-9ba4-c1a9873202ad/54b9c72f-d4f3-4db9-9e0e-0dc840b530bd.json";
import { ExtractorRunner, PersistenceStoreExtractorRunner } from "../0_interfaces/2_domain/ExtractorRunnerInterface.js";

const loggerName: string = getLoggerName(packageName, cleanLevel,"PersistenceStoreController");
let log:LoggerInterface = console as any as LoggerInterface;
Expand Down Expand Up @@ -89,20 +90,37 @@ export async function storeSectionFactory (
// #######################################################################################################################
export class PersistenceStoreController implements PersistenceStoreControllerInterface {
private logHeader: string;
// private adminExtractorRunner: PersistenceStoreExtractorRunner;

constructor(
private adminStore: PersistenceStoreAdminSectionInterface,
private modelStoreSection: PersistenceStoreModelSectionInterface,
private dataStoreSection: PersistenceStoreDataSectionInterface,
){
this.logHeader = 'PersistenceStoreController '+ modelStoreSection.getStoreName();
// this.adminExtractorRunner = new E
}

// #########################################################################################
getStoreName(): string {
return this.modelStoreSection.getStoreName();
}

// #############################################################################################
async handleQuery(section: ApplicationSection, query: QueryAction): Promise<ActionReturnType> {
// TODO: fix applicationSection!!!
log.info(this.logHeader,'handleQuery','section',section,'query',query);
log.info(this.logHeader,'this.dataStoreSection',this.dataStoreSection);
log.info(this.logHeader,'this.modelStoreSection',this.modelStoreSection);

const currentStore: PersistenceStoreDataSectionInterface | PersistenceStoreModelSectionInterface =
section == "data" ? this.dataStoreSection : this.modelStoreSection;
const result: ActionReturnType = await currentStore.handleQuery(query);

log.info(this.logHeader,'handleQuery','section',section,'query',query, "result", result);
return result;
}

// #############################################################################################
async handleAction(persistenceStoreControllerAction: PersistenceStoreControllerAction): Promise<ActionReturnType> {
switch (persistenceStoreControllerAction.actionType) {
Expand Down Expand Up @@ -567,21 +585,6 @@ export class PersistenceStoreController implements PersistenceStoreControllerInt
return result;
}

// // #############################################################################################
// async handleQuery(section: ApplicationSection, query: QueryAction): Promise<ActionReturnType> {
// // TODO: fix applicationSection!!!
// log.info(this.logHeader,'handleQuery','section',section,'query',query);
// log.info(this.logHeader,'this.dataStoreSection',this.dataStoreSection);
// log.info(this.logHeader,'this.modelStoreSection',this.modelStoreSection);

// const currentStore: PersistenceStoreDataSectionInterface | PersistenceStoreModelSectionInterface =
// section == "data" ? this.dataStoreSection : this.modelStoreSection;
// // const result: ActionReturnType = await currentStore.handleQuery(query);

// log.info(this.logHeader,'handleQuery','section',section,'query',query, "result", result);
// return result;
// }

// ##############################################################################################
async upsertInstance(section: ApplicationSection, instance:EntityInstance):Promise<ActionVoidReturnType>{
log.info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { packageName } from "../constants.js";
import { getLoggerName } from "../tools.js";
import { MiroirLoggerFactory } from "./Logger.js";
import { cleanLevel } from "./constants.js";
import { PersistenceInterface } from "../0_interfaces/4-services/PersistenceInterface.js";
import { PersistenceStoreLocalOrRemoteInterface } from "../0_interfaces/4-services/PersistenceInterface.js";
import { LocalCacheInterface } from "../0_interfaces/4-services/LocalCacheInterface.js";
import { DomainControllerInterface } from "../0_interfaces/2_domain/DomainControllerInterface.js";
import { DomainController } from "../3_controllers/DomainController.js";
Expand All @@ -38,7 +38,7 @@ MiroirLoggerFactory.asyncCreateLogger(loggerName).then(
// ################################################################################################
export class PersistenceStoreControllerManager implements PersistenceStoreControllerManagerInterface {
private persistenceStoreControllers: { [deploymentUuid: Uuid]: PersistenceStoreControllerInterface } = {};
private persistenceStore: PersistenceInterface | undefined; // receives instance of PersistenceReduxSaga
private persistenceStoreLocalOrRemote: PersistenceStoreLocalOrRemoteInterface | undefined; // receives instance of PersistenceReduxSaga
private localCache: LocalCacheInterface | undefined;
private domainController: DomainController | undefined;

Expand All @@ -49,16 +49,20 @@ export class PersistenceStoreControllerManager implements PersistenceStoreContro
) {}

// ################################################################################################
setPersistenceStore(persistenceStore: PersistenceInterface) {
this.persistenceStore = persistenceStore;
/**
* this is like prop drilling, this is not directly used by this class, but by the created DomainController (this.domainController)
* @param persistenceStore
*/
setPersistenceStoreLocalOrRemote(persistenceStore: PersistenceStoreLocalOrRemoteInterface) {
this.persistenceStoreLocalOrRemote = persistenceStore;
}

// ################################################################################################
getPersistenceStore(): PersistenceInterface {
if (this.persistenceStore) {
return this.persistenceStore;
getPersistenceStoreLocalOrRemote(): PersistenceStoreLocalOrRemoteInterface {
if (this.persistenceStoreLocalOrRemote) {
return this.persistenceStoreLocalOrRemote;
} else {
throw new Error("PersistenceStoreControllerManager getPersistenceStore no persistenceStore yet!");
throw new Error("PersistenceStoreControllerManager getPersistenceStoreLocalOrRemote no persistenceStore yet!");

}
}
Expand All @@ -78,11 +82,34 @@ export class PersistenceStoreControllerManager implements PersistenceStoreContro
}

// ################################################################################################
getDomainController(): DomainControllerInterface {
/**
* USED ONLY ON THE SERVER SIDE, INCLUDING EMULATED SIDE, FOR NOW.
* @returns
*/
getServerDomainController(): DomainControllerInterface {
if (this.domainController) {
return this.domainController;
} else {
throw new Error("PersistenceStoreControllerManager getDomainController no domainController yet!");
if (!this.localCache || !this.persistenceStoreLocalOrRemote) {
throw new Error(
"PersistenceStoreControllerManager getLocalCache no localCache or persitenceStore yet! localCache=" +
this.localCache +
" persistenceStore=" +
this.persistenceStoreLocalOrRemote
);
}

// TODO: domainController instance is also created in index.tsx and test-utils.tsx (the overall setup sequence). Isn't it redundant?
// TODO: THIS IS OVERLOADED BY EACH CALL TO addPersistenceStoreController!
this.domainController = new DomainController(
"server", // we are on the server, use localCache for queries upon receiving "remoteLocalCacheRollback" action
new MiroirContext(),
this.localCache, // implements LocalCacheInterface
this.persistenceStoreLocalOrRemote, // implements PersistenceStoreLocalOrRemoteInterface, instance of PersistenceReduxSaga
new Endpoint(this.localCache)
);
return this.domainController;
// throw new Error("PersistenceStoreControllerManager getServerDomainController no domainController yet!");
}
}

Expand All @@ -99,25 +126,6 @@ export class PersistenceStoreControllerManager implements PersistenceStoreContro
JSON.stringify({ storageType: config.admin.emulatedServerType })
);

if (!this.localCache || !this.persistenceStore) {
throw new Error(
"PersistenceStoreControllerManager getLocalCache no localCache or persitenceStore yet! localCache=" +
this.localCache +
" persistenceStore=" +
this.persistenceStore
);
}

// TODO: domainController instance is also created in index.tsx and test-utils.tsx (the overall setup sequence). Isn't it redundant?
this.domainController = new DomainController(
true, // we are on the server, use localCache for queries upon receiving "remoteLocalCacheRollback" action
new MiroirContext(),
this.localCache, // implements LocalCacheInterface
this.persistenceStore, // implements PersistenceInterface, instance of PersistenceReduxSaga
new Endpoint(this.localCache)
);


if (!adminStoreFactory) {
log.info(
"addPersistenceStoreController no admin store factory found for",
Expand Down
Loading

0 comments on commit 8ee0ebc

Please sign in to comment.