Skip to content

[REFACTOR] Refactor Scheduler following Clean Architecture#988

Merged
adrianq merged 13 commits intodevelopmentfrom
feature/scheduler-clean-architecture-refactor
Mar 13, 2025
Merged

[REFACTOR] Refactor Scheduler following Clean Architecture#988
adrianq merged 13 commits intodevelopmentfrom
feature/scheduler-clean-architecture-refactor

Conversation

@anagperal
Copy link
Contributor

@anagperal anagperal commented Feb 26, 2025

📌 References

📝 New refactor tasks

  • Decouple configRepository from other repositories that only need it to use the dataStoreClient
  • Think about how to refactor RepositoryFactory concept
  • Do not pass RepositoryFactory and Instance un use cases, only pass the necessary repositories
  • In the constructor of data repositories pass instead of Instance we should get D2Api or directly DataStoreClient when different instances are not needed
  • CompositionRoot needs to be refactored
  • Remove RepositoryConstructor concept from domain repositories where is not neccesary
  • Improve and refactor Scheduler tests using ts-mockito and adding integration tests

📝 Implementation

  • Refactor Scheduler following Clean Architecture: using MVP pattern
  • Refactor old code for a better understanding
  • Fix feedback component error when init app when not having feedback config in appConfig
  • Refactor SchedulerRepository to SchedulerExecutionInfoRepository and use cases that uses this repository
  • Decouple configRepository in SchedulerExecutionInfoD2ApiRepository and SyncRuleJobConfigD2ApiRepository
  • Fix add lastExecution also to scheduler-executions in datastore
  • First version of Scheduler test --> for the future use ts-mockito
  • Add new futures

📹 Screenshots/Screen capture

image

🔥 Is there anything the reviewer should know to test it?

  1. Create or edit a sync rule having the scheduler enabled
  2. Run scheduler using the corresponding config: yarn start-scheduler -c config.json
  3. Check if data is sync correctly

📑 Others

  • Any change in the GUI library? If so, what branch/PR?

  • Any change in the D2 Api? If so, what branch/PR?

@ifoche
Copy link
Member

ifoche commented Feb 26, 2025

Task linked: CU-8698310pt Refactor Scheduler

@anagperal anagperal requested a review from adrianq February 26, 2025 15:19
@anagperal anagperal marked this pull request as ready for review February 27, 2025 14:08
@anagperal anagperal requested a review from 9sneha-n February 27, 2025 14:34
Copy link
Contributor

@9sneha-n 9sneha-n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anagperal Awesome first PR for refactor.
Some comments below, we will probably need architect's opinion for some of them, then we can make it a standard and use it in all the next refactor PRs.

@@ -0,0 +1,27 @@
import { Instance } from "../../domain/instance/entities/Instance";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we add a decorator for all refactored files? So that we can keep track of all the files that are pending refactor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added comments on the refactored files and TODOs commenting on what they need to be fully refactored. Also in PR I have added some common reactoring tasks

export class SyncRuleJobConfigD2ApiRepository implements SyncRuleJobConfigRepository {
private dataStoreClient: StorageDataStoreClient;

constructor(private instance: Instance) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently in our projects, we are pass private api: D2Api to all repo constructors and then get the dataStoreClient from it. I am not sure why that is used instead of instance. We can check with Arnau and if that is recommended, shall we start using that pattern in all refactored repos?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code comment and task added for future implementation

public schedulerRepository(instance: Instance) {
const config = this.configRepository(instance);
return this.get<SchedulerRepositoryConstructor>(Repositories.SchedulerRepository, [config]);
public schedulerExecutionInfoRepository(instance: Instance) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to use this concept of repository-factory? I dont see it in our standard apps. We can create a separate PR to handle these "common" refactors, just making a note here for us.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code comment and task added for future implementation

import { Instance } from "../../instance/entities/Instance";
import { SchedulerExecutionInfo } from "../entities/SchedulerExecutionInfo";

export interface SchedulerExecutionInfoRepositoryConstructor {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again this comment in for separate PR for "common" refactor - should we used this concept of Constructor ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code comment and task added for future implementation

export class GetLastSchedulerExecutionInfoUseCase implements UseCase {
constructor(private repositoryFactory: RepositoryFactory, private localInstance: Instance) {}

public execute(): Promise<SchedulerExecutionInfo> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use Future instead of Promise? If its too big a change, we can add a note for future refactor and take care of it in separate PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added new Future entity and changed from Promise to Future

import { FileRulesDefaultRepository } from "../data/rules/FileRulesDefaultRepository";
import { RulesD2ApiRepository } from "../data/rules/RulesD2ApiRepository";
import { SchedulerD2ApiRepository } from "../data/scheduler/SchedulerD2ApiRepository";
import { SchedulerExecutionInfoD2ApiRepository } from "../data/scheduler/SchedulerExecutionInfoD2ApiRepository";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

common refactor note - We need to move to current way of implementing Composition root

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code comment and task added for future implementation

import { SchedulerExecutionInfo } from "../domain/scheduler/entities/SchedulerExecutionInfo";
import { Logger } from "./entities/Logger";

export class SchedulerPresenter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is SchedulerPresenter name too generic? Should we rename to something like SchedulerCLI or something similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed!


// Format date to keep timezone offset
const nextDate = moment(job.nextExecution.toISOString()).toISOString(true);
this.options.logger.info("scheduler", `Scheduling new sync rule ${name} (${id}) at ${nextDate}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we deconstruct options in the beginning one time, code would be more readable without all the 'this.options.' no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@@ -0,0 +1,6 @@
export type ScheduledJob = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these entities be moved to domain layer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved!

@@ -0,0 +1,7 @@
import { ScheduledJob } from "./ScheduledJob";

export interface SchedulerContract {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have note seen interfaces with functions used in this way in our standard apps. Shall we check if this type of usage is recommended or needs to be changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change this together with @xurxodev PR comments because I think this is more related with the architecture

@adrianq adrianq requested a review from xurxodev March 3, 2025 16:21
@anagperal
Copy link
Contributor Author

@anagperal Awesome first PR for refactor. Some comments below, we will probably need architect's opinion for some of them, then we can make it a standard and use it in all the next refactor PRs.

Thanks for all the comments @9sneha-n ! I have added comments in code and in the PR for common refactor tasks that we need to do in the future, also I have added them in the whiteboard of MD Sync (CC @adrianq).

@anagperal anagperal requested a review from 9sneha-n March 5, 2025 15:54
@anagperal anagperal changed the title Refactor Scheduler following Clean Architecture [REFACTOR] Refactor Scheduler following Clean Architecture Mar 5, 2025
Copy link
Contributor

@xurxodev xurxodev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @anagperal

I leave things to change that we have seen in the live review:

  • SyncRuleJobConfigD2ApiRepository and the use case that invoke it doesn't make sense. Better to use ListRulesUseCase passing required filter to avoid duplicate logic to retrive
  • Move contracts used by SchedulerCli from domain to near of schedulerCli. This contracts are only used by SchedulerCli and it's contracts of presentation.
  • Maybe make sense in the scheduler use cases pass directly the required repository because here the instance is not dynamic
  • For tests better to use ts-mockito to create test doubles as we saw in the coding dojo

@anagperal anagperal requested a review from xurxodev March 7, 2025 09:53
@anagperal
Copy link
Contributor Author

anagperal commented Mar 7, 2025

thanks @anagperal

I leave things to change that we have seen in the live review:

  • SyncRuleJobConfigD2ApiRepository and the use case that invoke it doesn't make sense. Better to use ListRulesUseCase passing required filter to avoid duplicate logic to retrive
  • Move contracts used by SchedulerCli from domain to near of schedulerCli. This contracts are only used by SchedulerCli and it's contracts of presentation.
  • Maybe make sense in the scheduler use cases pass directly the required repository because here the instance is not dynamic
  • For tests better to use ts-mockito to create test doubles as we saw in the coding dojo

Thanks @xurxodev!! All done except the part about changing the tests to use ts-mockito as you are adding it to another PR. I have noted this task for the future: Improve and refactor Scheduler tests using ts-mockito and adding integration tests to also add some integration testing to test syncs between two instances using the scheduler

Copy link
Contributor

@xurxodev xurxodev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @anagperal

Copy link
Contributor

@9sneha-n 9sneha-n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @anagperal !

@adrianq adrianq merged commit 670d1cd into development Mar 13, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants