Deposit Services system processes messages concurrently from both deposit and submission queues, utilizing dedicated listeners for each queue. This section outlines the workflow, detailing how messages are handled, processed, and how the corresponding resources are managed and updated throughout the deposit lifecycle.
Each message listener, one each for the deposit
and submission
queues, can process messages concurrently.
The submission
queue is processed by the SubmissionListener
, which resolves the Submission
resource represented
in the message, and hands off processing to the SubmissionProcessor
. The SubmissionProcessor
builds
a DepositSubmission
, which is the Deposit Services' analog of a Submission
containing all the metadata and
custodial content associated with a Submission
. After building the DepositSubmission
, the processor calls the
DepositTaskHelper
to perform the actual deposit. The DepositTaskHelper
delegates the deposit steps to an instance
of a DepositTask
. Importantly, the SubmissionProcessor
updates the Submission
resource in the repository as
being in progress.
The DepositTask
class contains the primary logic for packaging, streaming, and verifying the transfer of content from
the PASS repository to downstream repositories. The DepositTask
will determine if the transfer of custodial content
has succeeded, failed, or is indeterminable (i.e. an asynchronous deposit process that has not yet concluded). The
status of the Deposit
resource associated with the Submission
will be updated accordingly.
A failed Deposit
or Submission
is marked with Deposit.DepositStatus = FAILED
or Submission.AggregateDepositStatus = FAILED
.
When a resource has been marked FAILED
, Deposit Services will ignore any messages relating to the resource. Failed Deposit
resources will be retried as part of the DepositStatusUpdaterJob
job. Once all Deposit
resource are successful, the
failed Submission.AggregateDepositStatus
will be updated.
A resource will be considered as failed when errors occur during the processing of Submission
and Deposit
resources.
Some errors may be caused by transient network issues, or a server being rebooted. In the case of such failures,
Deposit Services will retry for n number of days after the Submission
is created. The number of days
is set in an application property named pass.status.update.window.days
.
Submission
resources are failed when:
- Failure to build the Deposit Services model for a Submission.
- There are no files attached to the Submission.
- Any file attached to the Submission is missing a location URI (the URI used to retrieve the bytes of the file).
- An error occurs saving the state of the
Submission
in the repository (arguably a transient error).
For more details, refer to the SubmissionProcessor
. Right now, when a Submission
is failed, manual intervention may be required.
Deposit Services does retry the failed Deposit
resources of the Submission
. However, some of the failure scenarios
above must be resolved by the user. It is possible the end-user will need to re-create the submission in the user
interface, and resubmit it.
Deposit
resources are failed when:
- An error occurs building a package.
- An error occurs streaming a package to a
Repository
(potentially transient). - An error occurs polling (potentially transient) or parsing the status of a
Deposit
. - An error occurs saving the state of a
Deposit
in the repository (again, potentially transient).
See DepositTask
for details. Deposits fail for transient reasons; a server being down, an interruption in network
communication, or invalid credentials for the downstream repository are just a few examples. As stated, DS will retry
failed Deposit
resources for n number of days after the creation of the associated Submission
. The number of days
is set in an application property named pass.status.update.window.days
.
Certain Spring sub-systems like Spring MVC, or Spring Messaging, support the notion of a "global" ErrorHandler
.
Deposit Services provides an implementation DepositServicesErrorHandler
, and it is used to catch exceptions thrown
by the DepositListener
, SubmissionListener
, and is adapted as a Thread.UncaughtExceptionHandler
and
as a RejectedExecutionHandler
.
Deposit Services provides a DepositServicesRuntimeException
(DSRE
), which has a field PassEntity resource
.
If the DepositServicesErrorHandler
catches a DSRE
with a non-null
resource, the error handler will test the type
of the resource, mark it as failed, and save it in the repository.
In essence: Deposit
and Submission
resources will be marked as failed if a DepositServicesRuntimeException
is
thrown from one of the JMS processors, or from the DepositTask
. As a developer, if an exceptional condition does
not warrant a failure, then do not throw DepositServicesRuntimeException
. Instead, consider logging a warning or
throwing a DSRE
with a null
resource. Likewise, to fail a resource, all you need to do is throw a DSRE
with a
non-null
resource. The DepositServicesErrorHandler
will do the rest.
Since the state of a resource can be modified at any time by any actor in the PASS infrastructure, the
DepositServicesErrorHandler
encapsulates the act of saving the failed state of a resource within a CRI
. The
pre-condition for updating the resource is that it must not be in a terminal state. For example, if the error
handler is updating the state from SUBMITTED
to FAILED
, but another actor has modified the state of the resource to
REJECTED
in the interim, the pre-condition will fail. Modifying the state of a resource after it reaches its
terminal state is not logical. In conclusion, the DepositServicesErrorHandler
will not mark a resource as failed
if it is in a terminal state.
Deposit Services is implemented using Spring Boot, which heavily relies on Spring-based annotations and conventions to
create and populate a Spring ApplicationContext
, arguably the most important object managed by the Spring runtime.
If you are unfamiliar with said annotations and conventions, the following resources would be beneficial to learning more
about them:
The entrypoint into the Deposit Services is the DepositApp
class. Spring beans are created entirely in Java code by the
DepositConfig
and JmsConfig
classes.
Deposit Services' primary artifact is a single self-executing jar. In the PASS infrastructure, the Deposit Services self-executing jar is deployed inside a simple Docker container.
Deposit Services can be built by running the following command:
mvn clean install
The main Deposit Services deployment artifact is located in deposit-core/target/pass-deposit-service-exec.jar
. It is
this jar file that is included in the Docker image for Deposit Services,
and posted on the GitHub Release page.