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

feat(clone): export domain/app #560

Merged
merged 4 commits into from
Oct 25, 2021
Merged

feat(clone): export domain/app #560

merged 4 commits into from
Oct 25, 2021

Conversation

kgajowy
Copy link
Contributor

@kgajowy kgajowy commented Oct 8, 2021

Substitute this line for a meaningful title for your changes

Overview

Please write a description. If the PR is hard to understand, provide a quick explanation of the code.

Designs

Link to the related design prototypes (if applicable)

Testing instructions

Please explain how to test the PR: ID of a dataset, steps to reach the feature, etc.

Feature relevant tickets

Link to the related task manager tickets


Checklist before submitting

  • Meaningful commits and code rebased on develop.
  • If this PR adds feature that should be tested for regressions when
    deploying to staging/production, please add brief testing instructions
    to the deploy checklist (docs/deployment-checklist.md)
  • Update CHANGELOG file

@kgajowy kgajowy changed the title feat(clone): domain feat(clone): export domain Oct 8, 2021
@vercel
Copy link

vercel bot commented Oct 8, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployments, click below or on the icon next to each commit.

marxan-storybook – ./app

🔍 Inspect: https://vercel.com/vizzuality1/marxan-storybook/EAQUYSbAv8yLxX2R9KJbHdviHb2K
✅ Preview: https://marxan-storybook-git-feature-clone-feature-base-vizzuality1.vercel.app

marxan – ./app

🔍 Inspect: https://vercel.com/vizzuality1/marxan/3CmuhjQUtztBZ9y93BZS5Nhc56Rc
✅ Preview: https://marxan-git-feature-clone-feature-base-vizzuality1.vercel.app


complete(archiveLocation: ArchiveLocation) {
this.archiveLocation = archiveLocation;
this.apply(new ArchiveReady(this.id, this.archiveLocation));
Copy link
Contributor

Choose a reason for hiding this comment

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

even if parts are not finished?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed in 99777f0

async export(id: ResourceId, kind: ResourceKind): Promise<ExportId> {
const parts: ClonePart[] = await this.resourcePieces.resolveFor(id, kind);
const exportInstance = this.eventPublisher.mergeObjectContext(
Export.project(id, parts),
Copy link
Contributor

Choose a reason for hiding this comment

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

ToDo: add scenario case. Right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't think so, why? Resolved pieces (components) could also be a scenario ones.

Copy link
Contributor

Choose a reason for hiding this comment

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

So when the kind will be ResourceKind.Scenario then it will still create an Export by Export.project?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Think of Export as coordinator of the request/work to do, regardless of what resource is exported (project or scenario).

Thus, relevant adapters of export/import for given piece will know how to act.

This may not be the best approach overall, so suggestions are welcomed!

Copy link
Member

Choose a reason for hiding this comment

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

I think the approach of leaving the resolution of work to do to adapters can work well.

I see the main difference in the top-level entity, which can be either a project (with zero? maybe at least one, or more scenarios) or a scenario.

One nuance is whether a scenario adapter should behave differently depending on whether it's being run as part of a project export or when cloning a single scenario within a project - the main difference here may actually be that we don't need to be thinking about downloadable artifacts but everything can/should happen in one single pass within the platform.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we are fine to implement cloning as a standalone procedure (pros: separation, speed/performance gains; cons: complicating the feature, keeping two processes in sync) we can still change the approach.

We shall also keep in mind that adapters may use some shared parts (one - extracting data, second variant for clone - putting it back, second variant for export - wrapping it into some file(s)

Copy link
Contributor

Choose a reason for hiding this comment

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

but Export.project(id suggests it is only for the project, and id is a project id, kind is not used here
and for kind === scenario, Export.project is used as well what is surprising

private constructor(
public readonly id: ExportId,
public readonly resourceId: ResourceId,
public readonly resourceKind: ResourceKind,
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure that kind is a good discriminator? Where it will affect the app logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

most likely shouldn't affect application logic. Could be that the same export may be used for both project and single-scenario export but not sure at this moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What you would propose?

import { PieceId } from './piece.id';
import { PieceLocation } from './piece-location';

export class ClonePart {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is that? Could you provide an example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Sikora00 its a component part listed in HLD. Will update the name to reflect it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed in b56996e

@hotzevzl
Copy link
Member

@kgajowy overall the approach looks good to me. One thing I recommend to keep in mind is that the core process here is really the cloning of projects or scenarios, with artifacts being a (fundamental) byproduct in the case of the project download/upload workflow (rather than cloning without intermediate steps).

I imagine this may mean still passing through some kind of intermediate representation of a scenario and project, of which the exportable and importable artifact may be a complex serialization - also taking into account that any such intermediate representation will often be something we should not assume that will reliably fit into memory, so persisting components' IR in some for may be unavoidable. But I'd consider the exportable/importable artifacts as a further step - all of this to be validated in terms of possible approaches, of course.

@kgajowy
Copy link
Contributor Author

kgajowy commented Oct 12, 2021

@kgajowy overall the approach looks good to me. One thing I recommend to keep in mind is that the core process here is really the cloning of projects or scenarios, with artifacts being a (fundamental) byproduct in the case of the project download/upload workflow (rather than cloning without intermediate steps).

I imagine this may mean still passing through some kind of intermediate representation of a scenario and project, of which the exportable and importable artifact may be a complex serialization - also taking into account that any such intermediate representation will often be something we should not assume that will reliably fit into memory, so persisting components' IR in some for may be unavoidable. But I'd consider the exportable/importable artifacts as a further step - all of this to be validated in terms of possible approaches, of course.

What would you propose @hotzevzl ? I am not sure if we can have any reliable data representation useful just for cloning (even the sqls) which would make it easy to then represent them in a different manner. How I imagined in there is that cloning would work exactly like export->import but without sharing the archive (thats why we keep geojsons/shapefiles rather than csv's with geometry)

@kgajowy kgajowy requested review from Sikora00 and Dyostiq October 13, 2021 05:28
Comment on lines 20 to 23
const parts: ExportComponent[] = await this.resourcePieces.resolveFor(
id,
kind,
);
Copy link
Contributor

Choose a reason for hiding this comment

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

what does ResourcePieces do?
Scans resources and determines what is exportable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Dyostiq yes. Could be the name used shall be resourcePiecesResolver ?

async export(id: ResourceId, kind: ResourceKind): Promise<ExportId> {
const parts: ClonePart[] = await this.resourcePieces.resolveFor(id, kind);
const exportInstance = this.eventPublisher.mergeObjectContext(
Export.project(id, parts),
Copy link
Contributor

Choose a reason for hiding this comment

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

but Export.project(id suggests it is only for the project, and id is a project id, kind is not used here
and for kind === scenario, Export.project is used as well what is surprising

) {}

async export(id: ResourceId, kind: ResourceKind): Promise<ExportId> {
const parts: ExportComponent[] = await this.resourcePieces.resolveFor(
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const parts: ExportComponent[] = await this.resourcePieces.resolveFor(
const pieces: ExportComponent[] = await this.resourcePieces.resolveFor(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

2082b21
fixed together with the Export.project.

Thanks for catching this!

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.

4 participants