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

Add automatic media job type compatibility #1136

Merged
merged 0 commits into from
Aug 24, 2022
Merged

Conversation

incjo
Copy link
Contributor

@incjo incjo commented Aug 9, 2022

makes progress against #1065 by building on top of #1062 by further expanding support for automatically handling media jobs.

It allows not writing dedicated media adapters in cases where the existing photo/video functionality is satisfactory. It also provides automatic interoperability with destinations that only provide a Media adapter.

Main contributions:

  • replaced MediaToPhotoConversionImporter and MediaToPhotoConversionExporter with generic versions that can support conversion between any two adapters: AnyToAnyImporter and AnyToAnyExporter
  • added special case adapters MediaExporterDecorator and MediaImporterDecorator which combine existing photo and video adapters to seamlessly cover the media job type.
  • added a compatibility layer TransferCompatibilityProvider (perhaps rename to AdapterCompatibilityProvider?) which attempts to build a substitute adapter upon not finding a real one. E.g. when a media job can't find a media importer, it will combine existing photo and video importers to perform the job.

@xokker xokker requested a review from jzacsh August 12, 2022 11:03
Copy link
Collaborator

@jzacsh jzacsh left a comment

Choose a reason for hiding this comment

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

sorry for the delay - I hadn't realized I hadn't submitted or finished my comments. Feel free to ping me in chat if my next replies aren't within a day.

*/
public class TransferCompatibilityProvider {

private static final String PHOTOS = "PHOTOS";
Copy link
Collaborator

Choose a reason for hiding this comment

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

since you're tackling this, please setup a new enum (just to make some micro-progress against #1065's wish to kill these magic strings). eg: org.datatransferproject.spi.transfer.DataVertical; fwiw I think spi.transfer is the right place (and not in types.common.models) because these are have historically been used and developed as "verticals" which are not strictly the same things as models but more of a meta concept. Pulling the enum out this way has two benefits:

  1. implicitly documents a bit of that distinction I just described
  2. lets us eventually update the transferextension's maps to use these documented enums as keys instead of the magic strings they take now

Copy link
Contributor Author

@incjo incjo Aug 23, 2022

Choose a reason for hiding this comment

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

Cool, I'll pick it up. I've been frustrated by this issue as well.

* sufficient.
*/
public AnyToAnyExporter(Exporter<AD, From> exporter, Function<From, To> converter,
Function<ContainerResource, ContainerResource> inputConverter) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

should inputConverter's parameterizations be To and From respectively?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, no. That's because an Exporter<PhotosContainerResource> takes ExportInformation<ContainerResource> as input to its export method. This container resource can be anything at all, e.g. IdOnlyContainerResource, DateRangeContainerResource, PhotosContainerResource, or even some private resource etc. For some reason, we're not enforcing strict typing in this case.

The From and To exporters might support different inputs and still be made compatible via the AnyToAnyExporter. For example, converting from PhotosExporter to MediaExporter might involve passing Id and DateRange resources unchanged and converting the PhotosContainerResource to MediaContainerResource.

Comment on lines 23 to 25
private final Exporter<AD, From> exporter;
private final Function<From, To> converter;
private final Function<ContainerResource, ContainerResource> inputConverter;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
private final Exporter<AD, From> exporter;
private final Function<From, To> converter;
private final Function<ContainerResource, ContainerResource> inputConverter;
private final Exporter<AD, From> exporter;
private final Function<From, To> containerResourceConverter;
private final Function<ContainerResource, ContainerResource> exportInformationConverter;

* export call. It's required because exporters often support various
* container resources as part of export information. E.g. photo exporters
* support DateRangeContainerResource, while media adapters might only
* support MediaContainerResource. Oftentimes, Function.identity() is
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oftentimes, Function.identity() is sufficient.

Maybe we just provide an overloaded constructor for that case then? (eg only takes two params, and automatically uses Function.identity() for the third arg?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is fair, I just don't have any such usages at the moment. I actually had that for the MicrosoftTransferExtension while it didn't have a dedicated media adapter.

@@ -23,6 +23,7 @@
*/
// TODO(#1065) fix primitives-obession causing us to key Providers on "PHOTOS" string rather
// than underlying file types.
@Deprecated
Copy link
Collaborator

Choose a reason for hiding this comment

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

everywhere you add this annotation, can you comment also what the recommended alternative is, as an inline comment? eg:

@Deprecated // prefer FooBar#baz


videos = List.of(
new VideoModel("v1", "", null, null, "d4", null, false),
new VideoModel("v2", "", null, null, "d5", "a3", false),
Copy link
Collaborator

Choose a reason for hiding this comment

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

should the album params on these photo or video models match the params of the media albums above? Or are they intentionally mismatched for testing purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, no reason. The particular data isn't relevant to the test.

videosImporter = (id, ex, ad, data) -> ImportResult.OK;
mediaImporter = new MediaImporterDecorator<>(photosImporter, videosImporter);

albums = List.of(new MediaAlbum("album1", "name1", "desc1"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

(optional nitpick) suggestion to make these lines consistent with your others below

Suggested change
albums = List.of(new MediaAlbum("album1", "name1", "desc1"),
albums = List.of(
new MediaAlbum("album1", "name1", "desc1"),

* Extracts a new VideosContainerResource from the relevant matching fields in a given
* MediaContainerResource.
*/
public static VideosContainerResource mediaToVideo(MediaContainerResource mediaContainer) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: consider adding test coverage of these two new static methods

@jzacsh
Copy link
Collaborator

jzacsh commented Aug 22, 2022

Do you have a pending PR somewhere that shows the final use of this? (eg: a PR that modifies a transfer extension?)

@incjo
Copy link
Contributor Author

incjo commented Aug 23, 2022

Do you have a pending PR somewhere that shows the final use of this? (eg: a PR that modifies a transfer extension?)

In our case, we're creating Media jobs without adding dedicated Media adapters. Essentially, we're leveraging the TransferCompatibilityProvider to automatically separate a MediaContainerResource into photos and videos, then use existing video and photo exporters and importers to do the remainder of the work while having the whole transfer happen under a single job.

This way we get to seamlessly support Media jobs without adding any new adapters, in our codebase or the destinations.

@jzacsh
Copy link
Collaborator

jzacsh commented Aug 29, 2022

hey @incjo did you accidentally revert this PR via a force-push? I'm not able to find the code we reviewed here and indeed if I click "compare" on this "incjo force-pushed the master branch from 6e97d8d to ed1f42b" it looks like your new code is gone (like adding @Deprecated lines, or your new classes); screenshot inlined below:
Screenshot of the force-push notification on github and the 6e97d8d56a0cb45f29386dd1c7bf0e46796311c5..ed1f42bc9a60b44ee85c2cd272758e108f6800cf diff

@incjo
Copy link
Contributor Author

incjo commented Aug 30, 2022

hey @incjo did you accidentally revert this PR via a force-push? I'm not able to find the code we reviewed here and indeed if I click compare it looks like your new code is gone

Yep, for some reason Github decides to close the PR if you force push the wrong thing which is exactly what I did. Thanks Github. I don't have permissions to reopen the PR. I've addressed your feedback and will probably just make a new PR with the changes.

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.

2 participants