Problem/Motivation
Unless cron is very carefully configured, the jobs for order close and renew can get requeued, resulting in multiple copies of a subscription's next recurring order.
For example, if Ultimate Cron is used to configure cron jobs, and Commerce Recurring's cron runs hourly while Advanced Queue's cron runs daily, then every hour, a RecurringOrderClose and RecurringOrderRenew job will be queued for an order that's up for renewal. By the time AQ gets to processing the queue, there will be multiple copies of these jobs. In particular, RecurringOrderRenew will create a new draft recurring order every time it's processed. If these erroneous duplicates are not spotted, customers will be charged multiple times
Proposed resolution
- Fix Advanced Queue so it support unique jobs: #2918866: Add support for unique jobs
- Fix our job plugins so they are unique
Original report by Almare
Due to my tests with recurring orders I think I found a misbehavior. I created for testing purposes a billing schedule of 1 hour. My cron is running every 15 minutes. My aim was to create every hour a recurring order for the bought products. The result of the recurring order is now that every 15 minutes recurring orders were created. Please see the attached images for more details. Maybe I made a mistake in my configurations.
| Comment | File | Size | Author |
|---|---|---|---|
| #105 | commerce_recurring.2931290-104.patch | 2.47 KB | zaporylie |
| #105 | commerce_recurring.2931290-104.TEST-ONLY-FAIL.patch | 1.7 KB | zaporylie |
| #102 | 2931290-102.patch | 791 bytes | jsacksick |
| #87 | 2931290-87.patch | 710 bytes | jsacksick |
| #84 | 2931290-84.patch | 7.87 KB | phannphong |
Issue fork commerce_recurring-2931290
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
Anonymous (not verified) commentedAlmare created an issue. See original summary.
Comment #2
bojanz commentedThere is no code that protects against requeueing, which is probably what you're seeing.
The assumed flow is this:
1) Cron runs, queues a number of expired orders
2) Advanced Queue runs, processes the queued orders (closing and renewing them)
3) Cron runs, queues the next number of expired orders.
The question here is, why doesn't #2 happen as expected on your setup.
Are you running Advanced Queue as a daemon (drush/console), or via cron?
Comment #3
Anonymous (not verified) commentedI use drush cron via crontab. Do you need additional infos about my set up?
Comment #4
bojanz commentedUnfortunately, I won't have time to investigate any additional bugs in the upcoming few weeks. You'll have to chase this one yourself for now.
Comment #5
Anonymous (not verified) commentedOk thank you. I will take a look into this behavior.
Comment #6
Anonymous (not verified) commentedI can close this issue, because this was part of a misconfiguration related to advancedqueue and ultimate cron. After figuring out that it was caused by my own settings I will close this issue.
Comment #7
Anonymous (not verified) commentedComment #8
bojanz commentedWhat was the misconfiguration?
Comment #9
Anonymous (not verified) commentedI changed the time interval when ultimate cron should run to 1 hour. After I switched to hourly execution the orders were created in the right time interval. At this point, without thinking what I have done, I thought I found the misconfiguration.
After your question I asked myself if this is really the behavior advanced queue should work and I took a look into advanced queue. I have now one question about the design of advanced queue. Where do we set the time when the next reccurring order should run? I mean I have a monthly billing period should I really set the time lap in ultimate cron to 1 month?? Surely not. So I tried to find the setting in the advanced queue plugin where we set the next execution time but I can't find the code which sets this time.
Edit: I found inside the cron.php the code where we create the new queue entries. It looks like we only decide if the recurring order is lower than the end date. This seems to me is not enough. Where do we calculate the time interval for the next run? I will reopen this issue.
Comment #10
Anonymous (not verified) commentedComment #11
Anonymous (not verified) commentedToday I debugged a little bit. It seems to me that there is no clear way how recurring orders should be created. The probem is everytime were all recurring orders with the state draft created. the billing cycle is not really implemented. The limitation of billing_period.ends is not a limitation, because it's at the moment always null or 000-00-00...
I had expected a different behavior how recurring orders were created without the need for a draft, which alway confused me by the way.
An example what I had expected:
Prerequisite: My system is configured to run the cron every 5 minutes.
On every cron run the recurring order module is fetching the recurring orders which are suitable for recurring. Means depending on minutly, hourly, weekly, monthly or yearly billing cycles the order were somehow identified, fetched and renewed. During the renew we fire an event for other modules to add for example another custom product, change the price or do something else with the recurring order. After that the normal payment process will run and the order will get, in the best case, the state completed. Of course their will be more things we have to remember during this process. This should only work as idea how it could work.
How it works currently:
Depending on the cron run time interval all recurring orders will be created and renewed. The only possible way to achieve a weekly execution is to set the recurring order runtime in ultimate cron (if its' possible their). The unsolved problem is what happens if we have 2 different billing cycles (weekly, monthly). This is currently not covered by this described setting.
I hope I could explain the problem.
Comment #12
franksj commentedThis matches what I'm seeing. I created a test subscription product with a 1 hour interval. If I run cron five times in a row, one right after the other, I'll get 5 charges one after the other. Each time I run cron, it should determine whether the subscription actually needs to be charged again. I should be able to run cron as many times as I want within the hour and only get the one valid charge.
I'm looking into this, too.
Comment #13
franksj commentedI changed to 1.x-dev and it seems to be honoring my billing schedule. I haven't diffed it to see what changed, but I *think* it may be working now.
Comment #14
Anonymous (not verified) commentedSwitched to dev and the same behavior occurs.
Comment #15
SchwebDesign commentedHi there, i'm getting this exact same issue as well. I set the billing schedule to daily, but every time cron runs it generates a new order and bills the charge to the user account.
This occurred when i was using the latest alphas/betas for each module, as well as the dev versions.
Currently I'm using this and it persists:
Drupal 8.5.3
commerce 2.6
commerce_license 2.x-dev
commerce_recurring 1.x-dev
recurring_period 1.x-dev
advancedqueue 1.0.0-beta3
Is it possible that something is misconfigured on my end? Would it help to provide my specific configuration?
What can I look in to to debug this or details can I get to help troubleshoot this?
Comment #16
SchwebDesign commentedfranksj, are things still working for you? Could you share your specific versions and settings?
Comment #17
Anonymous (not verified) commentedIt looks like that it is only working for monthly recurring.
Comment #18
SchwebDesign commentedThanks Almare. Do you use this on a production site and confirm what's working for your visitors?
Any advice on testing that things are working? I need to be sure subscribers won't be charged charged every time cron runs, but testing once a month isn't realistic either...
Comment #19
Anonymous (not verified) commentedNo I don't use it for production. I had too much trouble to get this really working. My hope is that some of the issues will be fixed in the next months.
Comment #20
franksj commentedMy products are monthly recurring and they're working correctly. As stated before, with hourly intervals, they will charge every time cron is run.
Comment #21
Anonymous (not verified) commented@franksj Thank you for the info. I will give it a try.
Off-topic: Which payments do you use for the recurring order, braintree?
Comment #22
heddnI think I was able to create a failing test. If we cron multiple times before the next billing cycle should kick off, then we create multiple orders.
In my case, I have a monthly and yearly subscription periods. If I set cron to run once a day, I'll create 30 orders for the single monthly subscription.
Comment #23
heddnComment #25
heddnIf someone uses ultimatecron, they can have the commerce recurring run on a faster schedule than the advanced queue.
The other thing I found (not directly related) is that if the order workflow gets changed from the default of recurring, then the transitioning to 'mark_paid' will fail and next time the order will be found as still in draft (but already paid) and will re-process as a new payment.
Comment #26
heddnI've opened #2984223: RecurringOrderManager assumes workflow, resulting in failures and duplicate payments.
Comment #27
heddnI wonder if we combine the fail test here w/ #2988470: Don't initiate payment of an already paid recurring order?
Comment #28
heddnHere's the fixes from #2988470-2: Don't initiate payment of an already paid recurring order combined in to see if that fixes things. No interdiff, because it is simply the patch from over there merged in here.
Comment #30
heddnNope, we cannot just merge those two things. Here we "do the right thing" and check if we've already queued an order before re-queueing another.
Comment #31
smccabe commentedShould the database query instead be a method available from advanced queue? Not to hold up this patch but maybe in the future.
The test could probably benefit from a comment making it a little clearer why we are running the cron twice back to back, otherwise someone might think it is an error and remove later. At a quick glance it looks like a typo
Comment #32
heddnI would /much/ prefer an API to confirm I'm not able to queue something multiple times. Something in advanced queue. Ideally something added to BackendInterface that I can optionally call to confirm I'm just about to duplicate something I've already queued.
For now, here's an updated comment.
Comment #33
heddnI came to realize that the previous tests weren't testing as much as I thought. Here's some improved tests.
Comment #34
heddnHere, we test a couple scenarios where cron was disabled or the advancedqueue cron job is out of sync with commerce_recurring.
Comment #35
joachim commentedMy project just got stung by the re-queueing problem. As a hotfix, the README should mention that cron timings have to be set up very carefully!
Comment #36
joachim commentedEDIT: nope, I wasn't thinking this through. closeOrder() will get called when a failed close is retried for dunning, so at that point, the order state will be needs_payment. Also, this bug also affects renewOrder()!
As a cleaner interim fix than #34, what having either RecurringOrderClose or RecurringOrderManager::closeOrder() simply ignore an order that is not in draft state?
Though I don't understand why this code allows for an order that's not in draft. When would that correctly happen?
Comment #37
joachim commentedComment #38
brunodboReroll of the patch in #34, after removal of
create()in #2952020: Remove static create() method from Cron class.Comment #39
joachim commentedComment #40
joachim commentedHere's a patch that relies on fixing Advanced Queue to support unique jobs: #2918866: Add support for unique jobs.
Tests won't pass because a) the AQ patch is needed, and b) #3017259: branch tests are failing
The changes I made to the test are much simpler than in the previous patch. I think all we need to test is that if our cron runs multiple times before AQ's cron runs, then no further jobs are queued.
In particular, some of the code in the tests in the previous patch confuses me:
I don't know why we need to recreated the Cron service each time. Existing test code just does:
so getting our Cron service from the container again seems to do the job. (I'm assuming the container destroys any services that rely on the time service when a new time service gets set on it, so that when you get our Cron again, it gets the time service injected fresh.)
I don't quite understand how these two scenarios work, or what they're testing.
At any rate, I don't think we need them: I think we can boil it down to ensuring that once a job it queued, another identical job won't get queued again.
Comment #41
porchlight commentedPatch #40 no longer applies.
Comment #42
bojanz commentedMarked #2998501: Duplicates commerce recurring ('commerce_recurring_order_close', 'commerce_recurring_order_renew') queues. as duplicate.
Comment #43
porchlight commentedRe-roll of patch in #40
Comment #44
Anonymous (not verified) commentedI made a test with latest dev version of commerce_recurring. Billing period is configured hourly. The cron execution is done every 15 min by ultimate cron. This is my current setup without the provided patch and I am not able to reproduce the described behavior of creating multiple orders anymore. Is this bug fixed by other code changes?
Comment #45
jwjoshuawalker commented@Almare Still affects me with latest dev as recent as today.
Will try some of these patches and get involved.
Comment #46
andyg5000I know there's some overlap in maintainership across the two modules required to get this fixed, but should just check the queue items before creating a matching one? The tricky part, I guess, is that advancedqueue can have different back-ends. Just a thought since this can cause big issues for people (I've been there)
Comment #47
bfuzze9898 commentedJust want to add that this is still an issue.
Drupal 8.9
commerce_recurring 1.0@beta5
Anxiously waiting for this to stabilize. I will test out some of these patches.
Comment #48
bfuzze9898 commentedThe other patches are quite old.
2931290-48.patch is my solution for 1.0@beta5.
Comment #49
bfuzze9898 commentedUpdated patch.
Comment #52
jonathanshawI rerolled #43, the approach that depends on a patch to advanced queue.
Comment #55
penyaskitoMerged head into the issue fork, so the generated patch applies.
Comment #56
johnpitcairn commentedI have (for testing):
Without patching, orders are being re-charged on every cron run, ie at 5 minute intervals.
The patch at #43 here, in conjunction with the unique jobs patch #58 against Advanced Queue at #2918866: Add support for unique jobs, does appear to fix the issue.
I had some confusion due to cron sleeping overnight (mac laptop), then the missed recurring orders being run one at a time on every subsequent 5-minute cron run until caught up, then hourly recurring orders resuming after that.
Comment #57
recidive commentedComment #58
andypostRelated core issue could help here, it also needs opinions and ideas
Comment #59
JeremyFrench commentedI think I have run into this issue, where although cron was working on a correct schedule there was a job failing that was preventing the queue from clearing this then resulted in multiple charge attempts being made once the queue was unblocked.
Comment #60
longwaveRaising this to critical, we should never trigger multiple charges no matter the configuration.
Comment #61
JeremyFrench commentedI like the queue unique approach, but in addition, I think we should put some defensive code in the Recurring Order Manager that checks that it needs to charge before applying charges. This may be a separate issue, but I think billing multiple times is something that should be avoided at all costs.
Comment #62
jonathanshawRecurringOrderManager now has strong defenses against the same order being paid multiple times.
I wonder if RecurringOrderManager::createOrder() should refuse to create an order if that would create two orders for the same subscription with the same billing period. Simple to enforce.
But better done in a seperate issue.
Comment #63
recidive commented@JeremyFrench @longwave can you confirm multiple orders were created for the same billing period, or just payment attempts?
Ultimately we need something to prevent multiple orders and double charges at any cost.
We need to capture these scenarios in automated tests of possible.
Also the merge request here will not get in unless the advanced queue patch gets in. It has no updates since almost a year ago.
Comment #64
JeremyFrench commented@recidive it looks like both orders and payments. I've seen #2988470 which looks to stop multiple payment per order, but not multiple orders being created.
Comment #65
marthinal commentedI think we can place the order (from Draft to Needs Payment). Anyway, we are doing the same from RecurringOrderManager::closeOrder()
Comment #66
marthinal commentedComment #68
marthinal commentedTest are broken https://www.drupal.org/project/commerce_recurring/issues/2931290. I think the error with the transition is related to https://www.drupal.org/node/3220507
IMHO it makes sense to place the order (from Draft to Needs Payment) when we move the recurring order to the queue. The order will not be added to the queue again because we check the state from Drupal\commerce_recurring\Cron::enqueueOrders().
Comment #69
a.dmitriiev commented+1 for changing the state of the order during cron processing. I my case there are hundreds of orders every week and number of active subscriptions is also more than 500+. So in addition it will be nice to also limit the number of entities (orders in
enqueueOrdersand subscriptions inenqueueSubscriptionsmethods) to prevent OOM problem, because loading 500 orders can be a problem. Then if the state is changed and for example 50 orders were processed in first run, the next time the other 50 orders will be processed, because the first 50 already have another state and the query result will be different. Alternatively maybe some batch processing should be implemented here? Not sure that it is easily possible with cron operations.Comment #70
arthur_lorenz commented>So in addition it will be nice to also limit the number of entities (orders in enqueueOrders and subscriptions in enqueueSubscriptions methods) to prevent OOM problem
I expanded #65 to limit the number of orders in `enqueueOrders` loaded at once to 50. I did not touch `enqueueSubscriptions` as subscriptions are not loaded, only their id's are returned from entity query.
Comment #71
a.dmitriiev commentedI am not sure that batch fix in #70 will fix Timeout problems. I think it is better to limit on query level and just leave the other orders for another cron run. Something like this:
Comment #72
arthur_lorenz commentedNo, this only prevents OOM issues. But can we then guarantee that all items are being queued? What if between 2 cron runs more than 50 items are being marked as `draft`?
Comment #73
jonathanshawThis seems like a valid bug, but also scope creep. Please open a seperate issue for this and post a patch for that there, unless there's a reason it must be entangled with the issue being worked on here.
Issues get committed faster when they're kept tightly focused. Patches are vastly easier to review when small.
Comment #74
arthur_lorenz commentedComment #75
jsacksick commentedComment #76
rinasek commentedComment #77
emil stoianov commentedLets make it Compatible with advancedqueue 1.0 also this related issue is now almost merged https://www.drupal.org/project/advancedqueue/issues/2918866
The changes will be UNIQUE_OVERWRITE_DUPLICATES instead of UNIQUE_OVERWRITE in
src/Plugin/AdvancedQueue/JobType/RecurringOrderRenew.php
src/Plugin/AdvancedQueue/JobType/RecurringOrderClose.php
Comment #78
jsacksick commentedhm I'd say "UNIQUE_DONT_OVERWRITE" as we don't want to queue duplicate jobs.
Comment #79
jonathanshawActually in the latest MR on #2918866: Add support for unique jobs the annotation is
allow_duplicates = falseComment #80
jsacksick commentedMarking this as needs work, we should favor leveraging the Advancedqueue support for unique jobs instead...
Comment #83
tbkot commentedPatch with the latest changes in MR
It should applied together with the patch for advancedqueue in #2918866: Add support for unique jobs
Comment #84
phannphong commentedI've updated the patch to work with PHP 7.x
Comment #85
jsacksick commented@phannphong: Could you upload an interdiff? Also FYI Commerce core itself has been requiring PHP8+ for a long time already.
Comment #86
jsacksick commentedSo I think the Advancedqueue patch isn't going to fully help here...
I wish we had flags on the orders (but as actual fields that we could use to detect whether the recurring order was already queued for closing / renewal).
We could use the order's data for that, but then we'd still keep querying for the order IDS on each cron run, so this isn't ideal... Perhaps better than nothing... Or we could maybe use the "locked" flag for this?
We lock the order once it's queued for closing and renewal, the advantage of this solution is that we'd stop refreshing the order. Since it was supposedly queued for closing and renewal, it shouldn't be refreshed in subsequent order loads?
Comment #87
jsacksick commentedCould anyone confirm whether the attached patch helps? We'd then skip relying on Advancedqueue for that...
Comment #88
johnpitcairn commentedHmm. We are allowing users with failing payments to put the recurring order back through checkout to update card details and pay it immediately.
We can unlock it before checkout but if the user abandons the process that might present a problem at next queueing query (every 15 minutes for us).
Comment #89
jsacksick commentedA job will be requeued in this case yes, but I don't think that is a problem? Because the initial job would be marked as a failure, so technically a "new" job would be requeued and it'd also fail.
We have other options...
$order->setData('commerce_recurring_order_close_queued', TRUE), the problem is orders would still be queried for "nothing" and would then be filtered out in the loopIn any case, I don't think relying on Advancedqueue is the answer to this problem anymore. I'd favor an option allow ingus to filter out orders already queued at the query level (i.e. the extra boolean field).
Comment #90
johnpitcairn commentedNo it's still in dunning retry, ie
needs_payment.Comment #91
jsacksick commented@John Pitcairn: I was referring to the Advancedqueue job state, not the order state? Not really sure what you're reporting here then? Because if the order has the "needs_payment" state, then it won't be re-queued the next time? Since we're only queuing draft orders?
Comment #92
johnpitcairn commentedOK so the state would prevent a requeue for us.
What else does a locked order imply though? What is that flag actually for?
I'd worry about further development deciding to assume only locked orders are in the queue. I also think there was some reason we don't save the order prior to putting it into checkout, which we'd have to to unlock it.
If the orders are already getting loaded and looped through then filtering on order data seems reasonable. If not and we are only querying for IDs then it probably should be a field for performance?
Comment #93
johnpitcairn commentedSorry cross post ... wouldn't a boolean (or lock) to indicate queueing need an update hook to set that for already queued orders? Is that feasible?
Comment #94
jsacksick commentedA locked order for example isn't refreshed on load. And if you're allowing your customers to resume checkout, you'd have to unlock them.
The data flag would work as I said, but we'd first query them for nothing.
Also, we could eventually skip saving the orders and just perform a direct update query to the DB (which would be more performant).
Comment #95
jonathanshawUsing lock for this makes me nervous, as per #88. It seems like an insufficiently robust solution, potentially with unexpected consequences or interactions with custom code, and generally increasing the WTF of an already complex mechanism.
What about #62:
Then we wouldn't be relying on AdvancedQueue. We could still use it's mechanism to avoid duplicates, but we'd not be reliant on it.
Comment #96
jsacksick commented@jonathanshaw: How is that related? This is about ensuring we don't queue twice the job for renewing / closing the recurring order for the current billing cycle.
In other words, there is code invoked and multiple duplicate queue jobs created before we even reach RecurringOrderManager::createOrder().
Whatever fix we pick has to happen from the cron service and should prevent the jobs from being queued more than once. We can pick the data flags, this is the easiest solution but it means we can't filter out orders that shouldn't be renewed / closed at the query level, which would be better performance wise.
Comment #97
jonathanshawMy thinking was the duplicate queue jobs would be harmless if RecurringOrderManager::createOrder() had the check I suggested.
I agree the order data seems like a natural place to store a flag.
Regarding performance, I wonder if commerce will one day change the data field to json and then we will be able to query it, something core is working on supporting #3343634: Add "json" as core data type to Schema and Database API
Comment #98
johnpitcairn commentedProbably silly idea: add a "queued" state?
Comment #99
jsacksick commentedNot a good idea, the workflow can be changed.
Maybe we'll just go with the data flag... And in theory, if the queue is properly processed, we shouldn't be loading the same orders over and over...
Comment #100
jonathanshawHow about we proceed with the unique queue support here, as it seems desirable even if not a complete solution. And do the data flag in a seperate issue?
Comment #101
jsacksick commentedThe "unique" job support that was introduced isn't really helping us...
It wouldn't prevent a job to be queued if it failed...
See #3460188: In some cases the duplicated jobs are created.
Comment #102
jsacksick commentedComment #103
zaporylieShall we, at the very least, also include a test to ensure no duplicates are created? I read carefully through this issue comments and it seems to me like #83 is the closest to the perfect test.
Performance issues are being discussed, especially in #69 - #73 with advice to work on them in a separate issue and not include in the scope here. I am a bit unsure about the latest proposal in #102 as it may close the door to making performance improvements in the future. This is a known limitation of the proposed approach as mentioned several times between #89 and #102.
This is a big pain, especially for merchants handling all their recurring payments on a frequent schedule (ex. hourly) or all at the same time (ex. first day of the month).
We could still go with the solution proposed in #102 if we plan to transition data property into json field as mentioned in #97 but given we're probably talking months if not years here I would rather opt for boolean field.
Comment #104
jsacksick commented#83 is leveraging the Advancedqueue patch, but once again, I'm no longer convinced relying on Advancedqueue to fix duplicates is the answer.
Also, we're collecting subscriptions by passing the order to the RecurringOrderManager, so looks like we can't easily avoid loading the orders without rewriting the cron job completely.
Additionally, #102 is a pragmatic approach to an issue that was opened 7 years ago in an attempt to not drag this further and revisit this later since we can't really find an agreement on a "perfect" solution.
I think the boolean makes more sense too, but it seems there were reservations about this approach too.
Comment #105
zaporylieI was only thinking about the subset of the test from #83, not the Unique AQ feature implementation. That being said I am not strongly opposed to implementing it as a safety measure, in addition to your proposed solution. It doesn't have to be done here and now though, could be done in a follow-up. That would address some concerns raised between #59 - #62
In regards to the boolean field, the only concern I see is in #93 and it's about setting a default value. I think this concern is valid whether we use lock, data, or boolean field. So if we don't change the query aspect of cron for now and leave it for a follow-up we may still be better, in a future-proof way, with boolean than data param. At least that's my opinion.
Anyways. combining #83 with #102 I was able to see that testing for running the cron twice (before running AQ cron) fixes the issue. I can still think of some scenarios where this can help - ex multiple instances of cron running at the same time but that's partially mitigated by cron lock.
Here are test results:
after the patch in #102
Comment #106
jsacksick commentedRegardless of the picked solution, we can't properly backfill I mea, it is ok to me if a "queued" boolean or whatever name we picked has 0 even if the recurring order is placed, what really matters to me is fixing the actual issue and making sure we no longer queue the same recurring order for closing / renewal.
Comment #107
zaporylieDo you think we should also change the method of loading the Order entity to OrderStorage::loadForUpdate to avoid race conditions? It kinda makes sense in this scenario and would further fail-safe proof the queuing mechanism. I am basing this on the fact that this issue was initially triggered by how differently people approach setting/splitting cron. That probably is a scope creep and a material for a followup though :)
Comment #108
jsacksick commentedUsing loadForUpdate() makes sense IMO, I don't really consider this a scope creep. The method didn't previously exist, so why not using it to make this even more robust.
Comment #110
zaporylieMR 31 is based on what we concluded so far:
- the commerce_recurring_queued boolean field is created - on install or via hook_update_N for existing websites. The field will be set to TRUE via cron
- Kernel test was introduced to ensure duplication issue is gone
- commerce requirement is bumped to account for orders now being loaded with OrderStorage::loadForUpdate to ensure the order is not being updated with 2 (or more) processes.
Some issues that we can work on in follow-up issues given we now have a param we can query against:
- adjust the order query to avoid orders that are already queued from being processed
- set a limit on the query to avoid processing more than reasonable number of orders at the same time
Comment #111
jsacksick commentedMR looks good to me, but let's see what other people think about it.
I think we should do that already no? We can probably add a
notExists()? Or maybe an OR condition group on notExists() + commerce_recurring_queued != 1.Comment #112
jsacksick commentedI think:
should be addressed in a followup issue yes.
Comment #113
jsacksick commentedMarking this as RTBC still, as we have tests and we've implemented the approach I favored (i.e. the boolean).
Perhaps we can update the test that was added to confirm the job types that were queued?
Basically, ensure that we have one "commerce_recurring_order_close" and another job for renewing the order "commerce_recurring_order_renew".
Comment #114
zaporylieAdded, although we already were testing this in CronTest::testActive(). Nevertheless, I think it makes sense to have an explicit test here and I added something I should have added before - asserting commerce_recurring_queued boolean value - 0 before cron runs, 1 after cron runs.
Comment #115
jsacksick commentedWent ahead and merged the request, let's move forward and address what's remaining as followup issues like suggested.
Comment #118
jsacksick commentedComment #119
zaporylieI added 2 child issues for followups.