Temporary Delete System for Safe Batch Automation and Lead Distribution
Project description
🐴 BarnYard: Temporary Delete System for Safe Batch Automation
BarnYard is a lightweight Python engine for safely distributing and processing leads or records across multiple concurrent automation scripts without data loss or duplication.
It introduces a temporary delete system that ensures a record is only removed when the task is truly complete. This protects your data even if crashes, force stops, or network interruptions occur.
Why BarnYard
In typical automation, you pull a record from a shared source such as SQL or CSV and delete it immediately to prevent other bots from processing the same record.
That works, but only until something goes wrong.
The Problem
If your automation:
- Crashes mid task,
- Is force stopped,
- Or times out midway,
Then that deleted record is gone forever even though the task never finished.
If you do not delete at all, you will have the opposite issue: duplicate processing by multiple bots.
This tension between safety and concurrency is what BarnYard solves.
💡 The BarnYard Solution
BarnYard replaces immediate deletion with a smarter two-phase delete system.
-
Temporary checkout When a lead is fetched, it is moved into a local barn (your workspace). This prevents duplicates but keeps it recoverable if something goes wrong.
-
Conditional delete
- If the task completes, the lead is shed (permanently removed).
- If the process fails, the lead is reinstated later for retry.
This ensures no record is ever lost or processed twice even when multiple scripts run in parallel.
How It Works
Each BarnYard instance, called an Engine, manages two local databases:
| File | Purpose |
|---|---|
<barn> |
The main barn containing active leads currently being processed. |
<barn>_reinstate |
The reinstate barn holding leads that expired or failed and need retry. |
✅ What You Get
| Feature | Description |
|---|---|
| Zero data loss | Records only delete after confirmed success. |
| Crash recovery | Reinstates unprocessed leads after failure. |
| Parallel safety | Multiple bots can safely share one data source. |
| Local first | Runs completely offline without Redis, servers, or queues. |
| Tunable safety | Adjust batch and calls to balance speed and reliability. |
| Clear visibility | Built-in display system shows barn activity in real time. |
Philosophy: High Scale, Low Cost
BarnYard follows a simple philosophy: Build automation that is affordable, failure tolerant, and massively scalable using only local resources.
It gives you queue level safety and concurrency control without needing servers or message brokers.
It is ideal for freelancers, small teams, or large environments running multiple headless bots.
The Lead Model
A lead (or record) is any list of values representing one unit of work:
["John Doe", "Premium", 27]
BarnYard automatically assigns each lead a unique integer key (ID) behind the scenes, keeping it safe and traceable.
🚀 The Engine Class
The Engine class is your main entry point. It controls how barns are created, managed, and displayed.
1. Initialize
import barnyard
barn = barnyard.Engine("my_barn")
This creates or attaches to a barn named "my_barn".
You can enable or disable display logs globally by setting the display parameter:
barn = barnyard.Engine("my_barn", display=True) # show logs
barn = barnyard.Engine("my_barn", display=False) # silent mode
2. Define a Fetch Function
Your add function must return a list of leads (lists of values). BarnYard handles key assignment internally.
def fetch_leads():
return [
["Alice", "Math", 20],
["Bob", "Science", 22],
["Charlie", "History", 19],
]
3. Fetch Leads Using next()
batch defaults to None, so you can skip it to enable automatic batch mode.
Example with explicit batch:
leads = barn.next(add=fetch_leads, batch=3, expire=30)
Example skipping batch (automatic batch):
leads = barn.next(add=fetch_leads, expire=30)
This:
- Pulls up to
batchleads at once or manages batch automatically ifbatch=None. - Temporarily removes them from the barn (safe checkout).
- Returns a list of dictionaries with
keyandvaluefields.
4. Process and Shed Safely
After successful processing:
for lead_dict in leads:
key = lead_dict['key']
value = lead_dict['value']
# ...process your lead...
barn.shed(key)
This permanently removes the lead, ensuring it will not reappear.
Batch and Calls Explained
BarnYard provides two controls that let you balance speed and safety when fetching leads.
| Parameter | Description | Trade Off |
|---|---|---|
batch |
Number of leads fetched at once. | Larger batch means faster but higher risk if stopped midway. |
calls |
Number of fetch cycles to repeat. | More calls means safer recovery but slower overall. |
Special Case: Using batch=None (Automatic Batch Mode)
If you omit batch or set batch=None, BarnYard will automatically manage the batch size for you. The logic:
- BarnYard reads the last used batch size from an internal cache file specific to your barn.
- This allows continuity across runs, so your batch size remains consistent unless you change it.
- If you call
next()with a different batch size than cached, BarnYard will finish processing the old batch size leads before switching to the new batch size. - This prevents mixing batches of different sizes that could cause instability or lead loss.
- The cache file is stored locally and updated automatically after each successful
next()run.
Using batch=None is recommended if you want BarnYard to adapt batch size dynamically without losing safety or creating duplicates.
🧮 Example with Automatic Batch
# First call sets batch to 5 (and caches it)
barn.next(add=fetch_leads, batch=5, calls=3)
# Later calls use cached batch size 5 if batch=None or omitted
barn.next(add=fetch_leads, batch=None, calls=3)
barn.next(add=fetch_leads, calls=3) # batch omitted defaults to None
# To change batch size, specify explicitly (will finish old batch first)
barn.next(add=fetch_leads, batch=2, calls=3)
Balancing Speed and Safety
| Situation | Recommended Setup |
|---|---|
| Stable system, low crash risk | batch=10, calls=1 |
| Moderate risk, shared machine | batch=5, calls=3 |
| High risk, unstable environment | batch=2, calls=10 |
Smaller batches reduce the risk of losing leads during sudden stops, at the cost of speed.
⏳ Max Query Duration
Every BarnYard operation has a maximum query time of 60 seconds.
This prevents hangs or deadlocks if a read or write stalls because of external input or output issues.
🖥 Display System
BarnYard includes a built-in display engine that visually tracks barn activity.
🧩 How Display Works
Every Engine instance has a global display mode set when you initialize it:
barn = barnyard.Engine("my_barn", display=True)
This acts as the default display setting for all operations on that engine.
However, every main function such as next(), info(), find(), and remove() has its own optional display argument (default: None).
| Value | Behavior |
|---|---|
None |
Inherits from the engine’s global display mode. |
True |
Forces display on for that specific function call. |
False |
Runs silently, overriding the engine’s default. |
This gives you flexible control.
Keep display on globally for clarity during development.
Turn it off per function when running automation in production.
Display Output Format
BarnYard logs barn activity lines with clear centered columns and status icons:
Sample output:
🐴 Barn: My_Barn | Action: Fetching New | Leads: 5 ✅ | 🕒 Time: 13:42:18
🐴 Barn: My_Barn | Action: Reinstating | Barn A. len: 12 ⚠️ | 🕒 Time: 13:42:48
The status icons (green check, yellow warning, red stop) help quickly monitor barn health.
Main Engine Functions
| Function | Description | Key Arguments | Returns |
|---|---|---|---|
next(add, *, batch=None, expire, calls=1, display=None) |
Fetches new or reinstated leads into the barn safely. | add: callable returning list of leads |
list[dict] |
shed(key) |
Permanently deletes a lead after successful completion. | key: int |
None |
info(display=None) |
Displays or returns all active and reinstated leads. | display: bool or None |
list[[lead, key]] |
find(key=None, value=None, display=None) |
Searches barn by key or lead value. | key or value |
Matches |
listdir(display=None) |
Lists all barns in the current directory. | None | list[str] |
remove(barn, display=None) |
Deletes a barn and all related reinstate data. | barn: str |
None |
📖 Example: Safe Automation Workflow
import barnyard
# Initialize engine
barn = barnyard.Engine("students", display=True)
def fetch_students():
return [
["Jane", "Math", 21],
["Chris", "English", 22],
["Tina", "Biology", 20],
]
# Step 1: Fetch new leads safely with automatic batch (batch defaults to None)
leads = barn.next(add=fetch_students, expire=30, calls=3)
# Step 2: Process safely
for lead_dict in leads:
key = lead_dict['key']
value = lead_dict['value']
print("Processing:", value)
barn.shed(key) # Delete only after success
# Step 3: View remaining leads
barn.info()
# Step 4: Clean up barn after all work is complete
barn.remove("students")
Key Takeaways
- BarnYard prevents data loss by replacing instant deletes with temporary holding.
- Each barn automatically restores unprocessed leads after crashes.
- The display system logs clear real-time status with color-coded icons.
- Smaller batches and multiple calls reduce data loss risk during interruptions.
- The automatic batch caching feature manages batch sizes seamlessly across sessions.
- BarnYard requires no external services, only Python, local files, and safe concurrency.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file barnyard-3.6.1.tar.gz.
File metadata
- Download URL: barnyard-3.6.1.tar.gz
- Upload date:
- Size: 117.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b396f9b9adf01124ae6244f3a42a4c2ca8c77afff3842f4bc2a26db5e29fe5a2
|
|
| MD5 |
301eecf0537384bf362020540515fff8
|
|
| BLAKE2b-256 |
3a26d7356864aa96a3158da49f20f6231a1493aada020f6f3a219834111aec11
|
File details
Details for the file barnyard-3.6.1-py3-none-any.whl.
File metadata
- Download URL: barnyard-3.6.1-py3-none-any.whl
- Upload date:
- Size: 129.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d3f153df6d2f8fe8704bee270539b7d4d0be1f781b84664b8755cbba0f3a2de
|
|
| MD5 |
047ba06c1ff84c348c2acea9732c39ea
|
|
| BLAKE2b-256 |
b8f70cf4fda5b17c58d747186c0ca98c0f372e9730e823b9609a293750539a12
|