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

[4372] Use semantic_data_id as editing context id #4397

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mcharfadi
Copy link
Contributor

@mcharfadi mcharfadi commented Jan 9, 2025

Bug: #4372

Pull request template

General purpose

What is the main goal of this pull request?

  • Bug fixes
  • New features
  • Documentation
  • Cleanup
  • Tests
  • Build / releng

Project management

  • Has the pull request been added to the relevant project and milestone? (Only if you know that your work is part of a specific iteration such as the current one)
  • Have the priority: and pr: labels been added to the pull request? (In case of doubt, start with the labels priority: low and pr: to review later)
  • Have the relevant issues been added to the pull request?
  • Have the relevant labels been added to the issues? (area:, difficulty:, type:)
  • Have the relevant issues been added to the same project and milestone as the pull request?
  • Has the CHANGELOG.adoc been updated to reference the relevant issues?
  • Have the relevant API breaks been described in the CHANGELOG.adoc? (Including changes in the GraphQL API)
  • In case of a change with a visual impact, are there any screenshots in the CHANGELOG.adoc? For example in doc/screenshots/2022.5.0-my-new-feature.png

Architectural decision records (ADR)

  • Does the title of the commit contributing the ADR start with [doc]?
  • Are the ADRs mentioned in the relevant section of the CHANGELOG.adoc?

Dependencies

  • Are the new / upgraded dependencies mentioned in the relevant section of the CHANGELOG.adoc?
  • Are the new dependencies justified in the CHANGELOG.adoc?

Frontend

This section is not relevant if your contribution does not come with changes to the frontend.

General purpose

  • Is the code properly tested? (Plain old JavaScript tests for business code and tests based on React Testing Library for the components)

Typing

We need to improve the typing of our code, as such, we require every contribution to come with proper TypeScript typing for both changes contributing new files and those modifying existing files.
Please ensure that the following statements are true for each file created or modified (this may require you to improve code outside of your contribution).

  • Variables have a proper type
  • Functions’ arguments have a proper type
  • Functions’ return type are specified
  • Hooks are properly typed:
    • useMutation<DATA_TYPE, VARIABLE_TYPE>(…)
    • useQuery<DATA_TYPE, VARIABLE_TYPE>(…)
    • useSubscription<DATA_TYPE, VARIABLE_TYPE>(…)
    • useMachine<CONTEXT_TYPE, EVENTS_TYPE>(…)
    • useState<STATE_TYPE>(…)
  • All components have a proper typing for their props
  • No useless optional chaining with ?. (if the GraphQL API specifies that a field cannot be null, do not treat it has potentially null for example)
  • Nullable values have a proper type (for example let diagram: Diagram | null = null;)

Backend

This section is not relevant if your contribution does not come with changes to the backend.

General purpose

  • Are all the event handlers tested?
  • Are the event processor tested?
  • Is the business code (services) tested?
  • Are diagram layout changes tested?

Architecture

  • Are data structure classes properly separated from behavioral classes?
  • Are all the relevant fields final?
  • Is any data structure mutable? If so, please write a comment indicating why
  • Are behavioral classes either stateless or side effect free?

Review

How to test this PR?

Please describe here the various use cases to test this pull request

  • Has the Kiwi TCMS test suite been updated with tests for this contribution?

@mcharfadi mcharfadi added this to the 2025.2.0 milestone Jan 9, 2025
@mcharfadi mcharfadi requested a review from sbegaudeau as a code owner January 9, 2025 09:01
@mcharfadi mcharfadi linked an issue Jan 9, 2025 that may be closed by this pull request
@mcharfadi mcharfadi force-pushed the mch/enh/editing_context_id branch 25 times, most recently from fd7d267 to 2ad3d10 Compare January 10, 2025 13:46
@mcharfadi mcharfadi force-pushed the mch/enh/editing_context_id branch 12 times, most recently from 8d9fe9a to c354ee1 Compare January 14, 2025 09:45
private final TransactionTemplate transactionTemplate;

private final ApplicationEventPublisher applicationEventPublisher;
//private final ApplicationEventPublisher applicationEventPublisher;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No sure if I should adopt a Parameters object or move some things around

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or I could remove ApplicationEventPublisher & TransactionTemplate

Copy link
Member

Choose a reason for hiding this comment

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

No sure if I should adopt a Parameters object or move some things around

I have not looked into this in details but there are some very specific places where we had to do that because we can't use Spring dependency injection but if the question arises anywhere else the answer is always no. This "parameters" object pattern is something we don't want to propagate.

@mcharfadi mcharfadi force-pushed the mch/enh/editing_context_id branch 2 times, most recently from 9406d58 to 92b25f9 Compare January 14, 2025 10:21
@mcharfadi mcharfadi force-pushed the mch/enh/editing_context_id branch from 92b25f9 to 37a7bb4 Compare January 14, 2025 10:21
Copy link
Member

@sbegaudeau sbegaudeau left a comment

Choose a reason for hiding this comment

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

I've stopped the review halfway because there is a small mis-understanding. I don't need you to remove the coupling between the editing context id and the project id to replace it by the exact same kind of coupling with the semantic data id.

I need you to make sure that downstream applications can couple the editing context id with something else and we should use the semantic data id as an example. I don't want to see the semantic data id being taken as an hardcoded dependency everywhere.

I first need a pull request making sure that the id of the project is now a string instead of an uuid and just that. After that, I need to be able to leverage that. For this second part, here's another acceptance criteria to ensure that your code works:

I need a piece of code in the project sirius-web-papaya which ensure that if the project id received by the backend is composed of UUID_OF_A_PAPAYA_PROJECT+demo-papaya so for example something like this:

http://localhost:5173/projects/f23c3cf0-7244-4892-8a58-82d40bfd1aa7+demo-papaya/edit/d4aa7077-707a-4cfb-a36f-1abdc46219e4

Then a new document with some Papaya content is added in the editing context. This document would not be saved in the editing context once it is persisted. I want to contribute a special IEditingContextLoader for Papaya that can change how data are loaded and a special IEditingContextSaver which changes how data are saved and I want to control how we are finding the editing context id from the project id.

I'm not even 100% sure that we need to change any of the code that you have modified to add this dependency to ISemanticDataSearchService.

@@ -30,10 +31,17 @@
*/
@QueryDataFetcher(type = "Project", field = "currentEditingContext")
public class ProjectCurrentEditingContextDataFetcher implements IDataFetcherWithFieldCoordinates<DataFetcherResult<String>> {

private final ISemanticDataSearchService semanticDataSearchService;
Copy link
Member

Choose a reason for hiding this comment

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

Please use the IEditingContextApplicationService here and leverage the ISemanticDataSearchService inside, since it's an application service it will help you not to forget using the @Transactionnal annotation which we need to have some proper transaction management.

@@ -63,7 +62,7 @@ public EditingContextLoader(ISemanticDataSearchService semanticDataSearchService
public void load(EditingContext editingContext, UUID projectId) {
this.editingContextProcessors.forEach(processor -> processor.preProcess(editingContext));

this.semanticDataSearchService.findByProject(AggregateReference.to(projectId))
this.semanticDataSearchService.findById(UUID.fromString(editingContext.getId()))
Copy link
Member

Choose a reason for hiding this comment

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

Is the projectId parameter still revenant now? Shouldn't we have something to select a relevant loader? We will see with a test.

@@ -74,7 +81,9 @@ public void persist(ICause cause, IEditingContext editingContext) {
if (editingContext instanceof IEMFEditingContext emfEditingContext) {
var applyMigrationParticipants = this.migrationParticipantPredicates.stream().anyMatch(predicate -> predicate.test(emfEditingContext));
new UUIDParser().parse(editingContext.getId())
.map(AggregateReference::<Project, UUID>to)
.flatMap(this.semanticDataSearchService::findById)
Copy link
Member

Choose a reason for hiding this comment

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

While it should work I suspect that the whole if block will end up being extracted in an IEditingContextSaver

Comment on lines +83 to +91
var optionalUUID = new UUIDParser().parse(editingContextId);
if (optionalUUID.isPresent()) {
var optionalSemanticData = this.semanticDataSearchService.findById(optionalUUID.get());
if (optionalSemanticData.isPresent() && optionalSemanticData.get().getId() != null) {
return this.projectSearchService.findById(optionalSemanticData.get().getProject().getId())
.map(project -> this.toEditingContext(project, optionalSemanticData.get().getId().toString()));
}
}
return Optional.empty();
Copy link
Member

Choose a reason for hiding this comment

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

I suspect that this is where a generic API will be needed

@@ -50,53 +52,68 @@ public class ObjectRestController {

private final IEditingContextDispatcher editingContextDispatcher;

public ObjectRestController(IEditingContextDispatcher editingContextDispatcher) {
private final ISemanticDataSearchService semanticDataSearchService;
Copy link
Member

Choose a reason for hiding this comment

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

You will need to use an application service here to leverage the @Transactionnal annotation (probably the same IEditingContextApplicationService?)

@@ -56,18 +58,25 @@ public class CommitRestController {

private final IEditingContextDispatcher editingContextDispatcher;

public CommitRestController(IEditingContextDispatcher editingContextDispatcher) {
private final ISemanticDataSearchService semanticDataSearchService;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment

@@ -48,9 +52,12 @@ public class DefaultProjectDataVersiongRestService implements IDefaultProjectDat

private final IObjectService objectService;

public DefaultProjectDataVersiongRestService(IDefaultObjectRestService defaultObjectRestService, IObjectService objectService) {
private final ISemanticDataSearchService semanticDataSearchService;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment

this.projectSearchService = Objects.requireNonNull(projectSearchService);
this.projectMapper = Objects.requireNonNull(projectMapper);
this.editingContextSearchService = Objects.requireNonNull(editingContextSearchService);
this.editingContextPersistenceService = Objects.requireNonNull(editingContextPersistenceService);
this.projectTemplateInitializers = Objects.requireNonNull(projectTemplateInitializers);
this.semanticDataSearchService = semanticDataSearchService;
Copy link
Member

Choose a reason for hiding this comment

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

require non null (same comment at various other locations)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lower the coupling between project and editing context
2 participants