Skip to content

Reorganize: Python Package Structure + Comprehensive Docs with Mermaid Diagrams#1

Open
itsXactlY wants to merge 9 commits into
rapmd73:mainfrom
itsXactlY:reorganize-project-structure
Open

Reorganize: Python Package Structure + Comprehensive Docs with Mermaid Diagrams#1
itsXactlY wants to merge 9 commits into
rapmd73:mainfrom
itsXactlY:reorganize-project-structure

Conversation

@itsXactlY
Copy link
Copy Markdown

What This PR Does

Major reorganization of JackrabbitDLM into a standard Python package layout with comprehensive documentation, Mermaid diagrams, and technical corrections discovered during code analysis.


Structural Changes

New Python Package: jackrabbitdlm/

jackrabbitdlm/
├── __init__.py              # Package root (version, exports Locker + encoding)
├── common/
│   └── encoding.py          # dlmEncode, dlmDecode, ShuffleJSON (shared, importable)
├── client/
│   └── locker.py            # Locker class (refactored, full docstrings)
├── server/
│   └── daemon.py            # Server daemon (cleaned, action handlers extracted)
├── tools/
│   ├── identity/            # Auth config generator
│   └── chart/               # Plotly log visualizer
└── benchmarks/
    └── lock_fighter.py      # Stress tester

New Directories

  • scripts/ — Shell helpers (install.sh, launch_dlm.sh, lock_wars.sh)
  • config/ — Configuration templates (defaults.yaml)
  • tests/ — Test suite (encoding roundtrip + ShuffleJSON)
  • docs/ — Extended documentation

Code Improvements

Encoding Module (jackrabbitdlm/common/encoding.py)

  • Extracted shared dlmEncode/dlmDecode/ShuffleJSON from inline duplication
  • Pre-computed lookup tables (ENCODE_TABLE, DECODE_TABLE) for O(1) performance
  • Full docstrings explaining the encoding is obfuscation, not encryption

Client Library (jackrabbitdlm/client/locker.py)

  • Cleaner API: talk(), _retry(), _retry_data() as internal methods
  • Docstrings for all public methods (Lock, Unlock, Put, Get, Erase, Version, IsDLM)
  • Imports encoding from common instead of duplicating code
  • Full backward compatibility with original DLMLocker.py

Server Daemon (jackrabbitdlm/server/daemon.py)

  • Extracted action handlers: _handle_lock(), _handle_unlock(), _handle_get(), _handle_put(), _handle_erase()
  • Configurable base dir via JACKRABBIT_BASE environment variable
  • Full docstrings with Wikipedia references for each concept
  • Identical protocol behavior — drop-in replacement

Shell Scripts

  • scripts/install.sh — Proper setup with venv creation and dependency install
  • scripts/launch_dlm.sh — Auto-restart wrapper with configurable paths
  • scripts/lock_wars.sh — Parallel stress test launcher with argument passthrough

README.md Overhaul

ASCII Art

  • slant font header (via pyfiglet) — clean, terminal-friendly

5 Mermaid Diagrams

  1. Architecture Overview (graph TB) — Clients → TCP → Server internals
  2. Request Flow (sequenceDiagram) — Lock/Put/Get/Unlock lifecycle with correct Lock vs DataStore separation
  3. Lock State Machine (stateDiagram-v2) — Lock states with note on entity separation
  4. Data Flow (flowchart TD) — Put with dynamic disk spillover thresholds
  5. Class Diagram (classDiagram) — All classes and their relationships

Sections

  • TL;DR with quick start code
  • Protocol Reference — Complete field descriptions, auth rules
  • Security Model — Ownership enforcement, blind vault, TTL, payload limits
  • Performance & Monitoring — All statistics explained
  • Comparison Table — vs Redis, ZooKeeper, Etcd, PostgreSQL
  • Wikipedia Links — Every deeper concept linked

Critical Technical Corrections

During code analysis, we discovered and documented several important details that were previously unclear:

1. Locks and DataStores Are Separate Entities

Locks and DataStores use separate IDs and should use different FileName values. A lock on "my_job" and data on "my_job:state" have independent lifecycles, ownership, and expiration.

# CORRECT: separate resources, separate IDs
lock = Locker("my_job", ID="lock-abc")
data = Locker("my_job:state", ID="data-xyz")

lock.Lock(expire=30)        # Acquires lock
data.Put(data="...", expire=60)  # Stores data
lock.Unlock()               # Lock released, data untouched
data.Erase()                # Data erased, lock unaffected

Unlock does NOT erase data. Erase does NOT unlock.

2. At 33% RAM, Both Lock AND Put Are Disabled

The MemoryOverloadCheck() is called in both _handle_lock and _handle_put. When process RSS exceeds 33% of total system RAM, both operations return {"Status": "NO"}. Only Get, Unlock, and Erase continue working.

3. Disk Spillover Threshold Is Dynamic

The ForceDisk logic has three conditions:

force_disk = (
    (ds_len > 16KB and expire > 10) or                        # Long TTL
    (ds_len > 16KB and ram_pct > 16.5%) or                    # Memory pressure
    (ds_len > 8KB and ram_pct > 24.75%)                       # High pressure
)
RAM Usage Lock Put Disk Threshold
< 16.5% 16 KB
16.5% - 24.75% 16 KB
24.75% - 33% 8 KB
≥ 33% NO NO n/a

Preserved

  • All original files kept alongside new structure for reference
  • LGPL-2.1 license unchanged
  • Zero additional dependencies beyond psutil (and plotly for charts)
  • Full backward compatibility with existing JSON-over-TCP protocol
  • Any language implementing the protocol will continue to work

Testing

cd JackrabbitDLM
python3 tests/test_encoding.py
# PASS: encode/decode roundtrip
# PASS: ShuffleJSON
# All tests passed!

Reorganized by itsXactlY with Hermes Agent. All technical details verified against source code.

itsXactlY and others added 9 commits April 20, 2026 17:56
Structure:
- jackrabbitdlm/ package with server/, client/, common/, tools/, benchmarks/
- scripts/ for shell helpers (install, launch, stress test)
- tests/ with encoding roundtrip tests
- config/ for defaults

README features:
- TL;DR section with quick start
- 5 Mermaid diagrams (architecture, sequence, state machine, data flow, class)
- Complete protocol reference
- Security model explanation
- All deeper concepts linked to Wikipedia
- Comparison table with Redis/ZK/Etcd

Original files preserved alongside new structure.
… threshold

- Sequence diagram: separate file names for lock (my_job) vs data (my_job:state),
  separate IDs (lock-abc vs data-xyz), independent cleanup
- State machine: removed Put/Erase transitions (those are data operations, not lock ops),
  added note about Lock/DataStore separation
- Data flow: dynamic threshold 16KB→8KB under memory pressure (>24.75% RAM),
  three-condition ForceDisk logic, threshold summary table
- Diagram now shows operation type fork (Lock/Put vs Get/Unlock/Erase)
- Memory check gates both Lock and Put at ≥33% RAM
- Memory Pressure Zones table: all four zones with Lock/Put/Erase behavior
- Critical note at top of section
## Summary

Major reorganization of JackrabbitDLM into a standard Python package with
comprehensive documentation, Mermaid diagrams, and corrected technical details.

## Structural Changes

### New Package Layout
    jackrabbitdlm/
    ├── __init__.py          # Package root (version, exports)
    ├── common/
    │   └── encoding.py      # dlmEncode, dlmDecode, ShuffleJSON (shared)
    ├── client/
    │   └── locker.py        # Locker class (refactored, docstrings)
    ├── server/
    │   └── daemon.py        # Main server daemon (cleaned, documented)
    ├── tools/
    │   ├── identity/        # Auth config generator
    │   └── chart/           # Log visualizer
    └── benchmarks/
        └── lock_fighter.py  # Stress tester

### New Directories
    scripts/                 # Shell helpers (install, launch, lock_wars)
    config/                  # Configuration templates
    tests/                   # Test suite (encoding roundtrip)
    docs/                    # Extended documentation

## Code Changes

### Encoding Module (jackrabbitdlm/common/encoding.py)
- Extracted shared encoding functions from inline code
- dlmEncode/dlmDecode/ShuffleJSON as importable functions
- Pre-computed ENCODE_TABLE/DECODE_TABLE for O(1) lookups
- Full docstrings with Wikipedia references

### Client Library (jackrabbitdlm/client/locker.py)
- Refactored Locker class with cleaner API
- Renamed internal methods (_retry, _retry_data, talk)
- Added docstrings for all public methods
- Import encoding from common module instead of inline
- Maintains full backward compatibility with original DLMLocker.py

### Server Daemon (jackrabbitdlm/server/daemon.py)
- Extracted action handlers (_handle_lock, _handle_unlock, _handle_get,
  _handle_put, _handle_erase) for readability
- Environment variable JACKRABBIT_BASE for configurable paths
- Full docstrings with Wikipedia references
- Maintains identical protocol behavior

### Shell Scripts
- scripts/install.sh: Proper setup with venv creation
- scripts/launch_dlm.sh: Auto-restart with configurable base dir
- scripts/lock_wars.sh: Parallel stress test launcher

## Documentation (README.md)

### Content
- ASCII art header (slant font via pyfiglet)
- TL;DR section with quick start
- 5 Mermaid diagrams:
  1. Architecture Overview (graph TB)
  2. Request Flow (sequenceDiagram) - shows Lock vs DataStore as
     SEPARATE entities with separate IDs
  3. Lock State Machine (stateDiagram-v2)
  4. Data Flow with Disk Spillover (flowchart TD) - correct dynamic
     thresholds (16KB → 8KB under memory pressure)
  5. Class Diagram (classDiagram)
- Complete protocol reference with field descriptions
- Security model documentation
- Performance & monitoring guide
- Comparison table with Redis/ZooKeeper/Etcd/PostgreSQL

### Critical Technical Corrections
- Locks and DataStores are SEPARATE entities with separate IDs
  (use different FileName: "my_job" for lock, "my_job:state" for data)
- At 33% RAM saturation, BOTH Lock AND Put are disabled (not just Put)
- Disk spillover threshold is dynamic: 16KB normal, drops to ~8KB
  when RAM > 24.75% (memory pressure)
- Unlock does NOT erase data; Erase does NOT unlock

## Preserved
- All original files kept alongside new structure for reference
- LGPL-2.1 license unchanged
- Full backward compatibility with existing JSON-over-TCP protocol
- Zero additional dependencies beyond psutil

## Testing
- tests/test_encoding.py: encode/decode roundtrip + ShuffleJSON verification
- All imports verified working

Co-authored-by: Hermes Agent <hermes@nousresearch.com>
…ith auth

If a resource was PUT or LOCKED with Name+Identity, subsequent
Get and Erase operations also require matching Name+Identity.
_check_identity() is called on every access to authenticated resources.

Updated Authentication Rules table:
- Split Get/Erase into anonymous vs authenticated cases
- Added explanation of how _check_identity() works
- Mismatch → NotOwner response
JackrabbitDLM now supports swappable storage backends:
- Memory (default, original behavior)
- Redis (host/port/db config)
- SQLite (persistent, file-based)
- Filesystem (JSON-on-disk)

Backend selected via config/backend option.
Factory registry pattern for runtime swapping.
backend.py now supports Memory, Redis, SQLite, Filesystem.
Merged with upstream origin/main.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant