Subscription Jobs
From a back-end perspective, Subcriptions come down to database records which maintain an appropriate status, and have associated payments that are billed appropriately. The Subscription "Jobs" are configurable tasks run in the background that ensure most of that maintenance is done in a recurring, automatic way.
What do they do
Subscription Jobs automate most of the maintenance tasks for existing subscription records, leaving to the user interface only the initial checkout of a subscription, and then those eventual tasks that require user interaction. Specifically, they:
- Traverse the payment methods associated with each subscription to check their validity
- Emit notifications on approaching tender expirations
- Identify subscriptions whose billing cycle is approaching, and prepare them for billing
- Bill the subscriptions
- Adequately deal with payment errors
Configuration properties
Most jobs in subscriptions need a similar pair of properties. In each of these pairs, one item represents the maximum amount of records that can be processed for one run of the corresponding job, and the other, how many threads will be devoted to process that amount of records.
What happens internally, is that the initial resultset retrieving the total records to be processed, is split among the available threads, and each thread processes a segment of that resultset.
The list of those properties is:
- subscriptions.autopending.batch.size
- subscriptions.autopending.threads
- subscriptions.autosuspend.batch.size
- subscriptions.autosuspend.threads
- subscriptions.mark.as.due.batch.size
- subscriptions.mark.as.due.threads
- subscriptions.tender.notification.batch.size
- subscriptions.tender.notification.threads
- subscriptions.payment.batch.size
- subscriptions.payment.threads
Additionally, these other properties are used:
subscriptions.expiration.notice.length
Used by the Tender Expiration Warning service. Indicates how many days in advance of expiration we should notify a customer.subscriptions.expiration.notification.nonrepeat.period
Also used by the Tender Expiration Warning service. Indicates a window period, in days, during which no new notifications should be issued in relation to an expiring tender.subscriptions.grace.period
Used by the Autosuspend and Autopending services. It indicates the length of time in days after expiration, for which an expired tender will be marked either as "pending" or as the more drastic "suspended"subscriptions.soft.declined.failover.max When a payment is soft-declined by the payment gateway service, this property indicates how many times the system should retry billing that subscription, before marking it as suspended.
Tuning
For the Subscription Jobs, tuning is not just a nice-to-have to improve performance, but it is absolutely critical for the proper functioning of the module.
These aspects might require special attention in relation to performance:
- Consider running the Subscription Jobs on a different web server altogether, with cache disabled.
- Treat threads as a valuable resource. Closely monitor the amount of threads the Scheduled Jobs generates over time.
- Do not rely on the provided default values for batch sizes and amount of threads dedicated to each job. Adequate values are heavily dependent on your subscriptions table's size.
- Bear in mind that, in a worst-case scenario, the maximum number of concurrent threads might require an equal number of database connections, so configure your DB connection pool accordingly.
Use cases this module supports
Aside from the initial checkout that generates a subscription, the Subscription Jobs assume no user interaction.
The Subscription Jobs only relinquish control of the subscription records once they are marked as SUSPENDED or PENDING. Direct user interaction is needed to deal with records in those states.
CANCELED subscriptions are completely ignored by the Subscription Jobs.
Extension points anticipated
More subscription jobs and statuses
The 6 statuses contemplated by default should cover most scenarios. However, adding a new subscription status should prove reasonably easy, provided that new jobs also ensure that subscriptions with a given status aren't left out of the transitions, or start accumulating without being processed.
Additional activities in the subscription payment workflow
This is in line with the standard extensibility quality of Broadleaf's workflow. For Subscriptions, a special workflow has been created, blSubscriptionPaymentWorkflow, that largely emulates the standard checkout workflow.
Additional logic in the "Validate And Confirm" activity
A version of this activity tailored for Subscriptions, ValidateAndConfirmSubscriptionPaymentActivity, has also been refactored (in relation to the original activity from the checkout workflow), in order to allow for an easier override of both the transaction payment, and the logic that interprets the response DTO coming from the payment gateway.