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

Provide async service API for sample management #1056

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package life.qbic.projectmanagement.application.api;

import java.util.Collection;
import java.util.List;
import static java.util.Objects.nonNull;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import life.qbic.projectmanagement.application.batch.SampleUpdateRequest.SampleInformation;
import life.qbic.projectmanagement.application.confounding.ConfoundingVariableService.ConfoundingVariableInformation;
import life.qbic.projectmanagement.application.sample.SampleIdCodeEntry;
import life.qbic.projectmanagement.application.sample.SamplePreview;
import life.qbic.projectmanagement.domain.model.sample.Sample;
import life.qbic.projectmanagement.domain.model.sample.SampleRegistrationRequest;
import org.springframework.lang.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
Expand All @@ -26,7 +33,7 @@
public interface AsyncProjectService {

/**
* Submits a project update request and returns a reactive {@link Mono<ProjectUpdateResponse>}
* Submits a project update request and returns a reactive {@link Mono< ProjectUpdateResponse >}
* object immediately.
* <p>
* The method implementation must be non-blocking.
Expand Down Expand Up @@ -73,10 +80,8 @@ Mono<ProjectUpdateResponse> update(
Mono<ExperimentUpdateResponse> update(ExperimentUpdateRequest request)
throws RequestFailedException, AccessDeniedException;



/**
* Submits a project creation request and returns a {@link Mono<ProjectCreationResponse>}
* Submits a project creation request and returns a {@link Mono< ProjectCreationResponse >}
* immediately.
* <p>
* This implementation must be non-blocking.
Expand All @@ -93,6 +98,58 @@ Mono<ProjectCreationResponse> create(ProjectCreationRequest request)
throws UnknownRequestException, RequestFailedException, AccessDeniedException;


/**
* Requests {@link SamplePreview} for a given experiment.
*
* @param experimentId the experiment ID for which the sample preview shall be retrieved
* @return a reactive stream of {@link SamplePreview} objects of the experiment
* @throws RequestFailedException if the request could not be executed
* @since 1.10.0
*/
Flux<SamplePreview> getSamplePreviews(String experimentId) throws RequestFailedException;
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 the project identifier as well as we need to make sure that the access rights are correct. This holds true for all api methods


/**
* Requests {@link SamplePreview} for a given experiment with pagination support.
*
* @param experimentId the experiment ID for which the sample preview shall be retrieved
* @param offset the offset from 0 of all available previews the returned previews should
* start
* @param limit the maximum number of previews that should be returned
* @return a reactive stream of {@link SamplePreview} objects in the experiment
* @since 1.10.0
*/
Flux<SamplePreview> getSamplePreviews(String experimentId, int offset, int limit);

/**
* Requests all {@link Sample} for a given experiment.
*
* @param experimentId the experiment ID for which the samples shall be retrieved
* @return a reactive stream of {@link Sample} objects
* @throws RequestFailedException in case the request cannot be executed
* @since 1.10.0
*/
Flux<Sample> getSamples(String experimentId) throws RequestFailedException;
Copy link
Member

Choose a reason for hiding this comment

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

Do we want to still expose the domain model sample here? Tracking which information we actually use later on is part of coming up with a good API.

Copy link
Member

Choose a reason for hiding this comment

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

Does this actually throw an exception or does the Flux have an error element?


/**
* Requests all {@link Sample} for a given batch
*
* @param batchId the batch ID the samples shall be retrieved for
* @return a reactive stream of {@link Sample} objects for the given batch
* @throws RequestFailedException in case the request cannot be executed
* @since 1.10.0
*/
Flux<Sample> getSamplesForBatch(String batchId) throws RequestFailedException;
Copy link
Member

Choose a reason for hiding this comment

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

Do we want to still expose the domain model sample here? Tracking which information we actually use later on is part of coming up with a good API.

Copy link
Member

Choose a reason for hiding this comment

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

Does this actually throw an exception or does the Flux have an error element?


/**
* Find the sample ID for a given sample code
*
* @param sampleCode the sample code (e.g. Q2TEST001AE) for the project
* @return a reactive container of {@link SampleIdCodeEntry} for the sample code
* @throws RequestFailedException in case the request cannot be executed
* @since 1.10.0
*/
Mono<SampleIdCodeEntry> findSampleId(String sampleCode) throws RequestFailedException;
Copy link
Member

Choose a reason for hiding this comment

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

Does this actually throw an exception or does the Mono have an error element?


/**
* Container of an update request for a service call and part of the
* {@link ProjectUpdateRequest}.
Expand Down Expand Up @@ -211,6 +268,7 @@ record ExperimentalVariable(String name, Set<String> levels, @Nullable String un

/**
* Container of experimental variables. Can be used in {@link #update(ExperimentUpdateRequest)}.
*
* @param experimentalVariables the list of experimental variables
* @since 1.9.0
*/
Expand Down Expand Up @@ -257,6 +315,7 @@ record ExperimentalGroup(@Nullable Long groupId, String name, int sampleSize,

/**
* A container for experimental groups. Can be used in {@link #update(ExperimentUpdateRequest)}
*
* @param experimentalGroups the list of experimental groups
* @since 1.9.0
*/
Expand Down Expand Up @@ -293,7 +352,9 @@ record ExperimentDescription(String experimentName, Set<String> species, Set<Str
}

/**
* A list of confounding variable information. Can be used in {@link #update(ExperimentUpdateRequest)}
* A list of confounding variable information. Can be used in
* {@link #update(ExperimentUpdateRequest)}
*
* @param confoundingVariables the variable information
*/
record ConfoundingVariables(List<ConfoundingVariableInformation> confoundingVariables) implements
Expand All @@ -307,10 +368,13 @@ record ConfoundingVariables(List<ConfoundingVariableInformation> confoundingVari

/**
* A service request to update an experiment
* @param projectId the project's identifier. The project containing the experiment.
*
* @param projectId the project's identifier. The project containing the experiment.
* @param experimentId the experiment's identifier
* @param body the request body containing information on what was updated
* @param requestId The identifier of the request. Please use {@link #ExperimentUpdateRequest(String, String, ExperimentUpdateRequestBody)} if it is not determined yet.
* @param body the request body containing information on what was updated
* @param requestId The identifier of the request. Please use
* {@link #ExperimentUpdateRequest(String, String,
* ExperimentUpdateRequestBody)} if it is not determined yet.
* @since 1.9.0
*/
record ExperimentUpdateRequest(String projectId, String experimentId,
Expand All @@ -319,9 +383,10 @@ record ExperimentUpdateRequest(String projectId, String experimentId,

/**
* A service request to update an experiment
* @param projectId the project's identifier. The project containing the experiment.
*
* @param projectId the project's identifier. The project containing the experiment.
* @param experimentId the experiment's identifier
* @param body the request body containing information on what was updated
* @param body the request body containing information on what was updated
* @since 1.9.0
*/
public ExperimentUpdateRequest(String projectId, String experimentId,
Expand All @@ -332,9 +397,10 @@ public ExperimentUpdateRequest(String projectId, String experimentId,

/**
* A service response from a {@link ExperimentUpdateRequest}
*
* @param experimentId the experiment's identifier
* @param body information about the update
* @param requestId the identifier of the original request to which this is a response.
* @param body information about the update
* @param requestId the identifier of the original request to which this is a response.
* @since 1.9.0
*/
record ExperimentUpdateResponse(String experimentId, ExperimentUpdateResponseBody body,
Expand All @@ -355,6 +421,45 @@ record ProjectCreationRequest(ProjectDesign design, ProjectContacts contacts,

}

/**
* A service request to create one or more new samples for a project.
*
* @param projectId the project ID of the project the samples shall be created for
* @param requests a collection of {@link SampleRegistrationRequest} items
* @since 1.10.0
*/
record SampleCreationRequest(String projectId, Collection<SampleRegistrationRequest> requests) {
Copy link
Member

Choose a reason for hiding this comment

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

I guess we need the experiment id here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

part of the request objects

public SampleCreationRequest(String projectId, Collection<SampleRegistrationRequest> requests) {
this.projectId = projectId;
this.requests = List.copyOf(requests);
Copy link
Member

Choose a reason for hiding this comment

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

You need to overwrite the getter for the requests as well to ensure they are not altered by accessing methods.

}
}

/**
* A service request to update one or more samples in a project.
*
* @param projectId the project ID of the project the samples shall be updated in
* @param requests a collection for {@link SampleUpdate} items
* @since 1.10.0
*/
record SampleUpdateRequest(String projectId, Collection<SampleUpdate> requests) {
Copy link
Member

Choose a reason for hiding this comment

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

You probably want to overwrite the getter for the requests as well to return an unmodifiable list.

public SampleUpdateRequest(String projectId, Collection<SampleUpdate> requests) {
this.projectId = projectId;
this.requests = List.copyOf(requests);
}
}

/**
* A container for a sample update request, containing the sample identifier and the updated
* information.
*
* @param sampleId the sample ID of the sample to update
* @param information the new information
* @since 1.10.0
*/
record SampleUpdate(String sampleId, SampleInformation information) {

}

/**
* A service response from a project creation request
Expand All @@ -366,7 +471,6 @@ record ProjectCreationResponse(String projectId) {

}


/**
* A service request to update project information.
*
Expand Down Expand Up @@ -441,6 +545,7 @@ boolean hasRequestId() {
* @since 1.9.0
*/
class UnknownRequestException extends RuntimeException {

private String requestId;

public UnknownRequestException(String message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
import life.qbic.logging.api.Logger;
import life.qbic.logging.service.LoggerFactory;
import life.qbic.projectmanagement.application.ProjectInformationService;
import life.qbic.projectmanagement.application.sample.SampleIdCodeEntry;
import life.qbic.projectmanagement.application.sample.SamplePreview;
import life.qbic.projectmanagement.domain.model.project.ProjectId;
import life.qbic.projectmanagement.domain.model.sample.Sample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.util.retry.Retry;
Expand Down Expand Up @@ -62,6 +66,31 @@ public Mono<ProjectCreationResponse> create(ProjectCreationRequest request)
throw new RuntimeException("not implemented");
}

@Override
public Flux<SamplePreview> getSamplePreviews(String experimentId) throws RequestFailedException {
Copy link
Member

Choose a reason for hiding this comment

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

Does this method throw or does the flux contain an error element?

throw new RuntimeException("not implemented");
}

@Override
public Flux<SamplePreview> getSamplePreviews(String experimentId, int offset, int limit) {
throw new RuntimeException("not implemented");
}

@Override
public Flux<Sample> getSamples(String experimentId) throws RequestFailedException {
Copy link
Member

Choose a reason for hiding this comment

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

Does this method throw or does the flux contain an error element?

throw new RuntimeException("not implemented");
}

@Override
public Flux<Sample> getSamplesForBatch(String batchId) throws RequestFailedException {
Copy link
Member

Choose a reason for hiding this comment

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

Does this method throw or does the flux contain an error element?

throw new RuntimeException("not implemented");
}

@Override
public Mono<SampleIdCodeEntry> findSampleId(String sampleCode) throws RequestFailedException {
throw new RuntimeException("not implemented");
}


@Override
public Mono<ExperimentUpdateResponse> update(
Expand Down