SlideShare a Scribd company logo
1 of 23
How to design
Resilient
Odoo Crons?
1.Introduction
Resilient
able to return quickly to a
previous good condition after
problems
Use case 1
Create an invoice for subscription
every month
Use case 2
Synchronize contacts with an
external tool every day
2. Pitfalls
Use case 1
Naive implementation
➔ Lack of robustness: One fails, all fail
➔ Monolithic: In case of timeout
everything is rolled back
● Need to process all data again
➔ Timeout (or rollback) end up with
inconsistent state if emails are sent
➔ If an invoice is skipped one month, it
will never invoice that month
➔ High risk of concurrent update: long
transaction updating data
➔ Run twice the same month, end up
with 2 invoices
# defined on sale.subscription
# Run Once a month
def _run_subscription_invoice(self):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
])
for subscription in subscriptions_to_invoice:
subscription.create_invoice()
Use case 2
Naive implementation
➔ Always process all the data
● Data to process will only grow
● It will timeout
➔ Monolithic: In case of timeout the
process will retry forever
➔ If it runs twice in the same day, it will
synchronize twice
➔ Run only once a day, if service is
unavailable at that specific time: no
synchronization that day
# Defined on res.partner
# Run Once a day
def _sync_partner(self):
partners = self.search([])
data = partners._prepare_data()
self._send_data(data)
What’s so bad
about timeout?
● It’s impossible to handle the
exception
● Next execution date is not updated.
It can run forever
● It’s impossible to handle the
exception
● Next execution date is not updated.
It can run forever
3. Features
Idempotent
# Use case 1
# Run Once a DAY
def _run_subscription_invoice(self):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
('next_invoice_date', '=', today),
])
for subscription in subscriptions_to_invoice:
subscription.create_invoice()
subscription.next_invoice_date +=
relativedelta(month=1)
# Use case 2
# Run whenever you want
def _sync_partner(self):
# Dirty is set to True when the partner is modified
partners = self.search([('dirty', '=', True)])
data = partners._prepare_data()
self._send_data(data)
partners.write({'dirty': False})
An operation that can be applied multiple
times without changing the result beyond
the initial application.
➔ Cron(rec) ~ Cron(rec); Cron(rec); ...
➔ Make sure that data are only
processed once
➔ Keep track of processed records
+ Frequencies of cron and data
processing don’t need to be correlated
+ It’s safe to retry
Incremental
# Use case 1
def _run_subscription_invoice(self):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
('next_invoice_date', '=', today),
])
for subscription in subscriptions_to_invoice:
subscription.create_invoice()
subscription.next_invoice_date += relativedelta(month=1)
self.env.cr.commit()
# Use case 2
def _sync_partner(self):
while True:
partners = self.search([('dirty', '=', True)],
limit=100)
if not partners:
break
data = partners._prepare_data()
self._send_data(data)
partners.write({'dirty': False})
self.env.cr.commit()
Split in small batches and save at the end
of each batch.
➔ Only possible if already idempotent
+ Timeout will be resolved eventually
+ Reduce transaction time, lower
concurrent update risk
! Data consistency at commit
! Commit are annoying for automated
testing
! Run more often than you would to
avoid timeout
Robust
def _run_subscription_invoice(self):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
('next_invoice_date', '=', today),
])
for subscription in subscriptions_to_invoice:
try:
subscription.create_invoice()
subscription.next_invoice_date +=
relativedelta(month=1)
self.env.cr.commit()
except Exception:
self.env.cr.rollback()
def _sync_partner(self):
while True:
partners = self.search([('dirty', '=', True)],
limit=100)
if not partners:
break
try:
data = partners._prepare_data()
self._send_data(data)
partners.write({'dirty': False})
self.env.cr.commit()
except Exception:
self.env.cr.rollback()
Prevent an issue on a single record to lead
to a general failure.
➔ Crash != Timeout, there is no retry
➔ Keep data consistency: rollback
+ Process all correct records
! Record processing can fail silently
! Be able to filter those who failed
Complete
def _run_subscription_invoice(self):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
# Today or before
('next_invoice_date', '<=', today),
])
for subscription in subscriptions_to_invoice:
try:
subscription.create_invoice()
subscription.next_invoice_date +=
relativedelta(month=1)
self.env.cr.commit()
except Exception:
self.env.cr.rollback()
Don’t leave a record never processed.
➔ If a record was not processed,
make sure it will be included next
time
+ Process all correct records
! Keep idempotence
! May end up processing forever bad
records
! Too many bad records can lead to
infinite retry
Verbose
def _sync_partner(self):
while True:
partners = self.search([('dirty', '=', True)],
limit=100)
if not partners:
Break
try:
data = partners._prepare_data()
self._send_data(data)
partners.write({'dirty': False})
self.env.cr.commit()
_logger.debug('Batch of partner is synced')
except Exception:
self.env.cr.rollback()
_logger.exception('Something went wrong')
Log what is happening.
➔ When something went wrong
➔ When processing is long
+ Processing records with an issue does
not fail silently anymore
! Don’t bloat the logs
Testable
def _run_subscription_invoice(self, auto_commit=True):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
('next_invoice_date', '<=', today),
])
for subscription in subscriptions_to_invoice:
try:
subscription.create_invoice()
subscription.next_invoice_date +=
relativedelta(month=1)
if auto_commit:
self.env.cr.commit()
_logger.debug('Invoice created')
except Exception:
if auto_commit:
self.env.cr.rollback()
_logger.exception('Failure with subscription')
Make automated testing easy.
➔ Tests are rolled back
➔ Not possible with commit
➔ Make possible to disable commit
+ No excuse not to test anymore
! Default behavior: Commit
Not stubborn def _run_subscription_invoice(self):
subscriptions_to_invoice = self.search([
('stage_id.category', '=', 'progress'),
('next_invoice_date', '<=', today),
# Leave 10 tries, then drop it
('next_invoice_date', '>', 10_days_ago),
...
def _sync_partner(self):
# dirty is an int, will be set to 5
# Try until dirty reaches 1
# 0: ok
# 1: issue after max retry
for partner in self.search([('dirty', '>', 1)])
try:
data = partner._prepare_data()
self._send_data(data)
partner.write({'dirty': 0})
self.env.cr.commit()
except Exception:
self.env.cr.rollback()
partner.dirty -= 1
self.env.cr.commit()
Don’t retry bad records forever.
➔ Useful if a lot of bad records or bad
records that will never be fixed
➔ Implementation case by case
+ Avoid wasting time to process those
records
+ Resolved Time Out eventually
! Jeopardize completeness
! Easy way to find dropped records
! Analyse real usage to find the good
trade off
4. Conclusion
Must Have
➔ Idempotent
➔ Incremental
➔ Robust
➔ Complete
Should have
➔ Verbose
➔ Testable
Could Have
➔ Not stubborn
Resilient Cron:
the recipe
Thank You

More Related Content

What's hot

Security: Odoo Code Hardening
Security: Odoo Code HardeningSecurity: Odoo Code Hardening
Security: Odoo Code HardeningOdoo
 
Odoo Performance Limits
Odoo Performance LimitsOdoo Performance Limits
Odoo Performance LimitsOdoo
 
Asynchronous JS in Odoo
Asynchronous JS in OdooAsynchronous JS in Odoo
Asynchronous JS in OdooOdoo
 
Odoo icon smart buttons
Odoo   icon smart buttonsOdoo   icon smart buttons
Odoo icon smart buttonsTaieb Kristou
 
Odoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best PracticesOdoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best PracticesOdoo
 
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Odoo
 
Odoo - Smart buttons
Odoo - Smart buttonsOdoo - Smart buttons
Odoo - Smart buttonsOdoo
 
Odoo - Business intelligence: Develop cube views for your own objects
Odoo - Business intelligence: Develop cube views for your own objectsOdoo - Business intelligence: Develop cube views for your own objects
Odoo - Business intelligence: Develop cube views for your own objectsOdoo
 
Odoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo
 
Odoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new apiOdoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new apiOdoo
 
An in Depth Journey into Odoo's ORM
An in Depth Journey into Odoo's ORMAn in Depth Journey into Odoo's ORM
An in Depth Journey into Odoo's ORMOdoo
 
The Odoo JS Framework
The Odoo JS FrameworkThe Odoo JS Framework
The Odoo JS FrameworkOdoo
 
Developing New Widgets for your Views in Owl
Developing New Widgets for your Views in OwlDeveloping New Widgets for your Views in Owl
Developing New Widgets for your Views in OwlOdoo
 
Scalable Django Architecture
Scalable Django ArchitectureScalable Django Architecture
Scalable Django ArchitectureRami Sayar
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upOdoo
 
Owl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOwl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOdoo
 
Odoo Experience 2018 - Inherit from These 10 Mixins to Empower Your App
Odoo Experience 2018 - Inherit from These 10 Mixins to Empower Your AppOdoo Experience 2018 - Inherit from These 10 Mixins to Empower Your App
Odoo Experience 2018 - Inherit from These 10 Mixins to Empower Your AppElínAnna Jónasdóttir
 
Odoo - Create themes for website
Odoo - Create themes for websiteOdoo - Create themes for website
Odoo - Create themes for websiteOdoo
 
Odoo External API
Odoo External APIOdoo External API
Odoo External APIOdoo
 
Introduction to rust: a low-level language with high-level abstractions
Introduction to rust: a low-level language with high-level abstractionsIntroduction to rust: a low-level language with high-level abstractions
Introduction to rust: a low-level language with high-level abstractionsyann_s
 

What's hot (20)

Security: Odoo Code Hardening
Security: Odoo Code HardeningSecurity: Odoo Code Hardening
Security: Odoo Code Hardening
 
Odoo Performance Limits
Odoo Performance LimitsOdoo Performance Limits
Odoo Performance Limits
 
Asynchronous JS in Odoo
Asynchronous JS in OdooAsynchronous JS in Odoo
Asynchronous JS in Odoo
 
Odoo icon smart buttons
Odoo   icon smart buttonsOdoo   icon smart buttons
Odoo icon smart buttons
 
Odoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best PracticesOdoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best Practices
 
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
 
Odoo - Smart buttons
Odoo - Smart buttonsOdoo - Smart buttons
Odoo - Smart buttons
 
Odoo - Business intelligence: Develop cube views for your own objects
Odoo - Business intelligence: Develop cube views for your own objectsOdoo - Business intelligence: Develop cube views for your own objects
Odoo - Business intelligence: Develop cube views for your own objects
 
Odoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo Online platform: architecture and challenges
Odoo Online platform: architecture and challenges
 
Odoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new apiOdoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new api
 
An in Depth Journey into Odoo's ORM
An in Depth Journey into Odoo's ORMAn in Depth Journey into Odoo's ORM
An in Depth Journey into Odoo's ORM
 
The Odoo JS Framework
The Odoo JS FrameworkThe Odoo JS Framework
The Odoo JS Framework
 
Developing New Widgets for your Views in Owl
Developing New Widgets for your Views in OwlDeveloping New Widgets for your Views in Owl
Developing New Widgets for your Views in Owl
 
Scalable Django Architecture
Scalable Django ArchitectureScalable Django Architecture
Scalable Django Architecture
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground up
 
Owl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOwl: The New Odoo UI Framework
Owl: The New Odoo UI Framework
 
Odoo Experience 2018 - Inherit from These 10 Mixins to Empower Your App
Odoo Experience 2018 - Inherit from These 10 Mixins to Empower Your AppOdoo Experience 2018 - Inherit from These 10 Mixins to Empower Your App
Odoo Experience 2018 - Inherit from These 10 Mixins to Empower Your App
 
Odoo - Create themes for website
Odoo - Create themes for websiteOdoo - Create themes for website
Odoo - Create themes for website
 
Odoo External API
Odoo External APIOdoo External API
Odoo External API
 
Introduction to rust: a low-level language with high-level abstractions
Introduction to rust: a low-level language with high-level abstractionsIntroduction to rust: a low-level language with high-level abstractions
Introduction to rust: a low-level language with high-level abstractions
 

Similar to How to Design Resilient Odoo Crons

Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patternsTomasz Kowal
 
Let it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTPLet it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTPMaciej Kaszubowski
 
Introduction to Event Sourcing in PHP
Introduction to Event Sourcing in PHPIntroduction to Event Sourcing in PHP
Introduction to Event Sourcing in PHPEvan McMahon
 
Chapter 12 transactions and concurrency control
Chapter 12 transactions and concurrency controlChapter 12 transactions and concurrency control
Chapter 12 transactions and concurrency controlAbDul ThaYyal
 
Automating Workflows for Analytics Pipelines
Automating Workflows for Analytics PipelinesAutomating Workflows for Analytics Pipelines
Automating Workflows for Analytics PipelinesSadayuki Furuhashi
 
Introduce cucumber
Introduce cucumberIntroduce cucumber
Introduce cucumberBachue Zhou
 
Do You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About ItDo You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About ItTobias Pfeiffer
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Dan Robinson
 
Data Modeling and WarehousingInstitution Affiliati
Data Modeling and WarehousingInstitution AffiliatiData Modeling and WarehousingInstitution Affiliati
Data Modeling and WarehousingInstitution AffiliatiOllieShoresna
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Howsatesgoral
 
Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18Maurice De Beijer [MVP]
 
Test Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocksTest Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocksRubén Bernárdez
 
Five finger audit
Five finger auditFive finger audit
Five finger auditBertil Hatt
 
Sql server lesson9
Sql server lesson9Sql server lesson9
Sql server lesson9Ala Qunaibi
 

Similar to How to Design Resilient Odoo Crons (20)

Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patterns
 
Let it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTPLet it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTP
 
Introduction to Event Sourcing in PHP
Introduction to Event Sourcing in PHPIntroduction to Event Sourcing in PHP
Introduction to Event Sourcing in PHP
 
09 sinkronisasi proses
09 sinkronisasi proses09 sinkronisasi proses
09 sinkronisasi proses
 
Chapter 12 transactions and concurrency control
Chapter 12 transactions and concurrency controlChapter 12 transactions and concurrency control
Chapter 12 transactions and concurrency control
 
Automating Workflows for Analytics Pipelines
Automating Workflows for Analytics PipelinesAutomating Workflows for Analytics Pipelines
Automating Workflows for Analytics Pipelines
 
Introduce cucumber
Introduce cucumberIntroduce cucumber
Introduce cucumber
 
Do You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About ItDo You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About It
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
 
Ruby For Startups
Ruby For StartupsRuby For Startups
Ruby For Startups
 
Data Modeling and WarehousingInstitution Affiliati
Data Modeling and WarehousingInstitution AffiliatiData Modeling and WarehousingInstitution Affiliati
Data Modeling and WarehousingInstitution Affiliati
 
Rspec
RspecRspec
Rspec
 
Dfd2
Dfd2Dfd2
Dfd2
 
Assignment pptx-12
Assignment pptx-12Assignment pptx-12
Assignment pptx-12
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18
 
Test Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocksTest Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocks
 
Five finger audit
Five finger auditFive finger audit
Five finger audit
 
Sql server lesson9
Sql server lesson9Sql server lesson9
Sql server lesson9
 

More from Odoo

Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Odoo
 
Odoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo
 
Keynote - Vision & Strategy
Keynote - Vision & StrategyKeynote - Vision & Strategy
Keynote - Vision & StrategyOdoo
 
Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Odoo
 
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityOdoo
 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooOdoo
 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseOdoo
 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Odoo
 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsOdoo
 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationOdoo
 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisOdoo
 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with OdooOdoo
 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooOdoo
 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo
 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to OdooOdoo
 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningOdoo
 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Odoo
 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelOdoo
 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldOdoo
 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to OdooOdoo
 

More from Odoo (20)

Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!
 
Odoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-Viewer
 
Keynote - Vision & Strategy
Keynote - Vision & StrategyKeynote - Vision & Strategy
Keynote - Vision & Strategy
 
Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14
 
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with Odoo
 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use Case
 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?
 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced Operations
 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organization
 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the Crisis
 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with Odoo
 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in Odoo
 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to Odoo
 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine Learning
 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification
 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping Label
 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 Fold
 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to Odoo
 

Recently uploaded

Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...
Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...
Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...anilsa9823
 
Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...
Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...
Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...Dave Litwiller
 
Progress Report - Oracle Database Analyst Summit
Progress  Report - Oracle Database Analyst SummitProgress  Report - Oracle Database Analyst Summit
Progress Report - Oracle Database Analyst SummitHolger Mueller
 
Mondelez State of Snacking and Future Trends 2023
Mondelez State of Snacking and Future Trends 2023Mondelez State of Snacking and Future Trends 2023
Mondelez State of Snacking and Future Trends 2023Neil Kimberley
 
Best Basmati Rice Manufacturers in India
Best Basmati Rice Manufacturers in IndiaBest Basmati Rice Manufacturers in India
Best Basmati Rice Manufacturers in IndiaShree Krishna Exports
 
M.C Lodges -- Guest House in Jhang.
M.C Lodges --  Guest House in Jhang.M.C Lodges --  Guest House in Jhang.
M.C Lodges -- Guest House in Jhang.Aaiza Hassan
 
Cracking the Cultural Competence Code.pptx
Cracking the Cultural Competence Code.pptxCracking the Cultural Competence Code.pptx
Cracking the Cultural Competence Code.pptxWorkforce Group
 
Unlocking the Secrets of Affiliate Marketing.pdf
Unlocking the Secrets of Affiliate Marketing.pdfUnlocking the Secrets of Affiliate Marketing.pdf
Unlocking the Secrets of Affiliate Marketing.pdfOnline Income Engine
 
Call Girls in Gomti Nagar - 7388211116 - With room Service
Call Girls in Gomti Nagar - 7388211116  - With room ServiceCall Girls in Gomti Nagar - 7388211116  - With room Service
Call Girls in Gomti Nagar - 7388211116 - With room Servicediscovermytutordmt
 
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...Aggregage
 
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdfRenandantas16
 
VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...
VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...
VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...Suhani Kapoor
 
Insurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usageInsurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usageMatteo Carbone
 
Understanding the Pakistan Budgeting Process: Basics and Key Insights
Understanding the Pakistan Budgeting Process: Basics and Key InsightsUnderstanding the Pakistan Budgeting Process: Basics and Key Insights
Understanding the Pakistan Budgeting Process: Basics and Key Insightsseri bangash
 
Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...Roland Driesen
 
Grateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdfGrateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdfPaul Menig
 
Regression analysis: Simple Linear Regression Multiple Linear Regression
Regression analysis:  Simple Linear Regression Multiple Linear RegressionRegression analysis:  Simple Linear Regression Multiple Linear Regression
Regression analysis: Simple Linear Regression Multiple Linear RegressionRavindra Nath Shukla
 
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...amitlee9823
 

Recently uploaded (20)

Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...
Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...
Lucknow 💋 Escorts in Lucknow - 450+ Call Girl Cash Payment 8923113531 Neha Th...
 
Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...
Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...
Enhancing and Restoring Safety & Quality Cultures - Dave Litwiller - May 2024...
 
Progress Report - Oracle Database Analyst Summit
Progress  Report - Oracle Database Analyst SummitProgress  Report - Oracle Database Analyst Summit
Progress Report - Oracle Database Analyst Summit
 
Mondelez State of Snacking and Future Trends 2023
Mondelez State of Snacking and Future Trends 2023Mondelez State of Snacking and Future Trends 2023
Mondelez State of Snacking and Future Trends 2023
 
Best Basmati Rice Manufacturers in India
Best Basmati Rice Manufacturers in IndiaBest Basmati Rice Manufacturers in India
Best Basmati Rice Manufacturers in India
 
M.C Lodges -- Guest House in Jhang.
M.C Lodges --  Guest House in Jhang.M.C Lodges --  Guest House in Jhang.
M.C Lodges -- Guest House in Jhang.
 
Cracking the Cultural Competence Code.pptx
Cracking the Cultural Competence Code.pptxCracking the Cultural Competence Code.pptx
Cracking the Cultural Competence Code.pptx
 
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabiunwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
 
Unlocking the Secrets of Affiliate Marketing.pdf
Unlocking the Secrets of Affiliate Marketing.pdfUnlocking the Secrets of Affiliate Marketing.pdf
Unlocking the Secrets of Affiliate Marketing.pdf
 
Call Girls in Gomti Nagar - 7388211116 - With room Service
Call Girls in Gomti Nagar - 7388211116  - With room ServiceCall Girls in Gomti Nagar - 7388211116  - With room Service
Call Girls in Gomti Nagar - 7388211116 - With room Service
 
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
 
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
 
VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...
VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...
VIP Call Girls Gandi Maisamma ( Hyderabad ) Phone 8250192130 | ₹5k To 25k Wit...
 
Insurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usageInsurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usage
 
Understanding the Pakistan Budgeting Process: Basics and Key Insights
Understanding the Pakistan Budgeting Process: Basics and Key InsightsUnderstanding the Pakistan Budgeting Process: Basics and Key Insights
Understanding the Pakistan Budgeting Process: Basics and Key Insights
 
Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...
 
Grateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdfGrateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdf
 
Regression analysis: Simple Linear Regression Multiple Linear Regression
Regression analysis:  Simple Linear Regression Multiple Linear RegressionRegression analysis:  Simple Linear Regression Multiple Linear Regression
Regression analysis: Simple Linear Regression Multiple Linear Regression
 
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
 
Forklift Operations: Safety through Cartoons
Forklift Operations: Safety through CartoonsForklift Operations: Safety through Cartoons
Forklift Operations: Safety through Cartoons
 

How to Design Resilient Odoo Crons

  • 1.
  • 4. Resilient able to return quickly to a previous good condition after problems
  • 5. Use case 1 Create an invoice for subscription every month
  • 6. Use case 2 Synchronize contacts with an external tool every day
  • 8. Use case 1 Naive implementation ➔ Lack of robustness: One fails, all fail ➔ Monolithic: In case of timeout everything is rolled back ● Need to process all data again ➔ Timeout (or rollback) end up with inconsistent state if emails are sent ➔ If an invoice is skipped one month, it will never invoice that month ➔ High risk of concurrent update: long transaction updating data ➔ Run twice the same month, end up with 2 invoices # defined on sale.subscription # Run Once a month def _run_subscription_invoice(self): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), ]) for subscription in subscriptions_to_invoice: subscription.create_invoice()
  • 9. Use case 2 Naive implementation ➔ Always process all the data ● Data to process will only grow ● It will timeout ➔ Monolithic: In case of timeout the process will retry forever ➔ If it runs twice in the same day, it will synchronize twice ➔ Run only once a day, if service is unavailable at that specific time: no synchronization that day # Defined on res.partner # Run Once a day def _sync_partner(self): partners = self.search([]) data = partners._prepare_data() self._send_data(data)
  • 11. ● It’s impossible to handle the exception ● Next execution date is not updated. It can run forever
  • 12. ● It’s impossible to handle the exception ● Next execution date is not updated. It can run forever
  • 14. Idempotent # Use case 1 # Run Once a DAY def _run_subscription_invoice(self): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), ('next_invoice_date', '=', today), ]) for subscription in subscriptions_to_invoice: subscription.create_invoice() subscription.next_invoice_date += relativedelta(month=1) # Use case 2 # Run whenever you want def _sync_partner(self): # Dirty is set to True when the partner is modified partners = self.search([('dirty', '=', True)]) data = partners._prepare_data() self._send_data(data) partners.write({'dirty': False}) An operation that can be applied multiple times without changing the result beyond the initial application. ➔ Cron(rec) ~ Cron(rec); Cron(rec); ... ➔ Make sure that data are only processed once ➔ Keep track of processed records + Frequencies of cron and data processing don’t need to be correlated + It’s safe to retry
  • 15. Incremental # Use case 1 def _run_subscription_invoice(self): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), ('next_invoice_date', '=', today), ]) for subscription in subscriptions_to_invoice: subscription.create_invoice() subscription.next_invoice_date += relativedelta(month=1) self.env.cr.commit() # Use case 2 def _sync_partner(self): while True: partners = self.search([('dirty', '=', True)], limit=100) if not partners: break data = partners._prepare_data() self._send_data(data) partners.write({'dirty': False}) self.env.cr.commit() Split in small batches and save at the end of each batch. ➔ Only possible if already idempotent + Timeout will be resolved eventually + Reduce transaction time, lower concurrent update risk ! Data consistency at commit ! Commit are annoying for automated testing ! Run more often than you would to avoid timeout
  • 16. Robust def _run_subscription_invoice(self): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), ('next_invoice_date', '=', today), ]) for subscription in subscriptions_to_invoice: try: subscription.create_invoice() subscription.next_invoice_date += relativedelta(month=1) self.env.cr.commit() except Exception: self.env.cr.rollback() def _sync_partner(self): while True: partners = self.search([('dirty', '=', True)], limit=100) if not partners: break try: data = partners._prepare_data() self._send_data(data) partners.write({'dirty': False}) self.env.cr.commit() except Exception: self.env.cr.rollback() Prevent an issue on a single record to lead to a general failure. ➔ Crash != Timeout, there is no retry ➔ Keep data consistency: rollback + Process all correct records ! Record processing can fail silently ! Be able to filter those who failed
  • 17. Complete def _run_subscription_invoice(self): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), # Today or before ('next_invoice_date', '<=', today), ]) for subscription in subscriptions_to_invoice: try: subscription.create_invoice() subscription.next_invoice_date += relativedelta(month=1) self.env.cr.commit() except Exception: self.env.cr.rollback() Don’t leave a record never processed. ➔ If a record was not processed, make sure it will be included next time + Process all correct records ! Keep idempotence ! May end up processing forever bad records ! Too many bad records can lead to infinite retry
  • 18. Verbose def _sync_partner(self): while True: partners = self.search([('dirty', '=', True)], limit=100) if not partners: Break try: data = partners._prepare_data() self._send_data(data) partners.write({'dirty': False}) self.env.cr.commit() _logger.debug('Batch of partner is synced') except Exception: self.env.cr.rollback() _logger.exception('Something went wrong') Log what is happening. ➔ When something went wrong ➔ When processing is long + Processing records with an issue does not fail silently anymore ! Don’t bloat the logs
  • 19. Testable def _run_subscription_invoice(self, auto_commit=True): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), ('next_invoice_date', '<=', today), ]) for subscription in subscriptions_to_invoice: try: subscription.create_invoice() subscription.next_invoice_date += relativedelta(month=1) if auto_commit: self.env.cr.commit() _logger.debug('Invoice created') except Exception: if auto_commit: self.env.cr.rollback() _logger.exception('Failure with subscription') Make automated testing easy. ➔ Tests are rolled back ➔ Not possible with commit ➔ Make possible to disable commit + No excuse not to test anymore ! Default behavior: Commit
  • 20. Not stubborn def _run_subscription_invoice(self): subscriptions_to_invoice = self.search([ ('stage_id.category', '=', 'progress'), ('next_invoice_date', '<=', today), # Leave 10 tries, then drop it ('next_invoice_date', '>', 10_days_ago), ... def _sync_partner(self): # dirty is an int, will be set to 5 # Try until dirty reaches 1 # 0: ok # 1: issue after max retry for partner in self.search([('dirty', '>', 1)]) try: data = partner._prepare_data() self._send_data(data) partner.write({'dirty': 0}) self.env.cr.commit() except Exception: self.env.cr.rollback() partner.dirty -= 1 self.env.cr.commit() Don’t retry bad records forever. ➔ Useful if a lot of bad records or bad records that will never be fixed ➔ Implementation case by case + Avoid wasting time to process those records + Resolved Time Out eventually ! Jeopardize completeness ! Easy way to find dropped records ! Analyse real usage to find the good trade off
  • 22. Must Have ➔ Idempotent ➔ Incremental ➔ Robust ➔ Complete Should have ➔ Verbose ➔ Testable Could Have ➔ Not stubborn Resilient Cron: the recipe

Editor's Notes

  1. In this talk we are going to see how design cron for the real life condition. We will start with 2 naives use cases See what problems thoses use cases will faces see all the feature the cron should have to Solve the use cases and how to implement those feature What are the benefit of those feature and some aspect you should pay attention on
  2. Let’s start with the introduction
  3. First, some definition. You probably all know what is à cron in odoo It’s a piece of code that run periodically à certain number of time (possible infinite number of time) But what resilient mean ? In other word, when something bad happen, for example à crash, à timeout, things going to be ok eventually without human intervention Now let’s see the use case we are going to study
  4. Telecom company for exemple That create invoice for customer monthly subscription and probably send àn email with the invoice. For the purpose of the talk we keep it minimum. Only monthly subscription, no payment or anything fancy, juste create the invoice, validate it and send an email
  5. Here we want to synchronize contact information with another software at least once a day We imagine that we have an api that we can call as much time as we want with as much partner data per call as we want
  6. Now let’s see what could possibly go wrong.
  7. What do we do ? The script run once a month, since we need to generate only once a month an invoice. I told you it’s a naive solution We search for all open subscription and called à method for each of them create_invoice In that method, the invoice is posted and the mail is sent to the customer We don’t know how many data to process but probably a lot, if not now, in the future, if the business grow the cron should continue to work So timeout will likelity to happen. In case of timeout: Leave the method call, leave the cron management, stop everything and write in the log timeout => Email sent, are sent, if transaction rollback, you’ll get twice the email (or more) => The transaction may be long, and you’ll get number for invoice that take à lock, during the potentially long transaction, nobody can post an invoice :D => RUn manually, because things went wrong, run twice (human mistake) got two invoice for that month
  8. Here, we get all the partner We prepare the call to the api And send everything in one call, let’s assume it’s ok on their side which won’t be the case probably He, we are more less sure the data to process will grow and thus time out If we timeout during the call send_data, probably that will be update but we never get the answer and try forever If it timeout before it’s à bit better, we don’t use the ressource of the api but still retry forever
  9. Now let see the feature our cron should have to avoid the pitfalls And à way to implement them
  10. Idempotent: What is it Basicaly you run once or you run many times (on the very same data) it’s the same result How to implement: Have a flag, that will be turn off once the data is processed And it solve at least Run twice the same month, end up with 2 invoices If it runs twice in the same day, it will synchronize twice Make the cron run as much time as you want, does not change the fact that your data willl be processed only when needed Processed only data that need to be processed, and this more often is a step away from the timeout Alone it does not solve many things but it’s à pre-requisite for the other feature To solve them
  11. Pre-requisite Idempotent If fail after few batch, you need to know those batch is already done How to implementer it In case of invoice it’s easy, after each invoice commit For partners, need to split in batch: there is many way to to so => Make more calls with only 100 data: APi should like it much better => Size of the batch may be adapt: Keep transaction small less than few seconds Commit often: Does not help to avoid timeout but end them. In case of interaction with external system it’s not à silver bullet. => Process more often should do the trick. Do no commit everywhere, make sure that data are consistent => Do not commit when invoice is created but not posted When you want to test your code, commit can be anoying since test should be rolled back and it won’t be the case anymore More on that later Solved: Monolithic: In case of timeout everything is rolled back Need to process all data again Timeout forever
  12. So far if something went wrong, the cron stopped And retry the next execution date, it’s not like à timeout and if we start with The first wrong data, the cron will stop forever and not data will be processed anymore until The data is fixed (or the code) We want to prevent this. À single failure will not prevent other record to work Try; except and rollback the bacth if the bach was wrong. Issue with big batch, if only one record lead to issue the batch will be rollabck Small batch or make sure you have filter wrong data. Keep try catch in case you missed something => Record failing silently: more on that later =>
  13. We want to make sure all data that should be processed are processed The implementation is different for each cron. The idea, make sure you’ll don’t leave someone behind Idempotence is of course something you need to keep in mind. Be complete but also indempotent, don’t process twice => Issue that raise, you have à huge backlog of wrong data that you keep Forever: TImeout and you never process other data anymore It depends on your use case, may happen quickly or not. If it may happen quicly, we will see later how to mitigate this effect
  14. We want to solve, the issue we introduce with robustness Fail silently Obviously: write in the log if something went wrong More verbose than in this sample Write exception message, traceback can be handy Log.exception as well May be interesting to log the progress, not every record or in debug mode Don’t bloat the log
  15. Quite simple, we want to offer the caller to not commit, so test can properly rollaback Especially for testing purpose Default behavior should commit.
  16. Finally, Remember that you can have à lot of wrong data that will always fail and take more and more time of processing During the cron ? Here we try to mitigate that by finding a trade off to completeness Not useful for every use case Only when you have lot of wrong data that you cannot exclude easily and that won’t be fixed quicly For the invoicing We only check few days ago so if a subscription failed to much we ignore it and we need to fix it manually And probably create the invoice manually For syncing partner, Here we sync one by one, the api may not like it, since it will be à lot of calls Dirty is set to 5, each try -1, If it’s ok then 0 If not -1 We stop at 1, so 1 means to much retry and 0 means everything is fine
  17. See this as a check list when you implement your cron. Be carefull it’s not always that obvious than we saw in the use case.