317 lines
8.3 KiB
Markdown
317 lines
8.3 KiB
Markdown
# ddd_domain
|
|
|
|
Database-driven application using [half-orm](https://github.com/half-orm/half-orm) with [half-orm-dev](https://github.com/half-orm/half-orm-dev) workflow.
|
|
|
|
**Database:** `ddd_domain`
|
|
**Generated with:** half-orm-dev==1.0.0-a32
|
|
|
|
---
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
```bash
|
|
# Install half-orm-dev (includes half-orm)
|
|
# IMPORTANT: Install the version specified in .hop/config.
|
|
# Replace <version> by the value of hop_version.
|
|
pip install half-orm-dev==<version>
|
|
```
|
|
|
|
**Version requirement:** This project requires `half-orm-dev >= 1.0.0-a32`
|
|
|
|
### Clone This Project
|
|
|
|
```bash
|
|
# Clone project with automatic database setup (use git_origin in .hop/config)
|
|
half_orm dev clone <git_origin>
|
|
```
|
|
|
|
This will:
|
|
- Clone the repository and checkout `ho-prod` branch
|
|
- Configure database connection in `/etc/half_orm/ddd_domain` or `${HALFORM_CONF_DIR}/ddd_domain`
|
|
- Restore production schema from `.hop/model/schema.sql`
|
|
- Generate Python ORM classes in `ddd_domain/` directory
|
|
|
|
---
|
|
|
|
## 📖 Development Workflow
|
|
|
|
This project uses **half-orm-dev** for database versioning and patch management.
|
|
|
|
### 1. Create a Release
|
|
|
|
```bash
|
|
# Create new minor release (e.g., 0.17.0)
|
|
half_orm dev release create minor
|
|
|
|
# Creates ho-release/0.17.0 branch
|
|
# Creates .hop/releases/0.17.0-patches.toml
|
|
```
|
|
|
|
### 2. Create a Patch
|
|
|
|
# Create patch (auto-added as candidate)
|
|
half_orm dev patch create <number>-<description>
|
|
|
|
# Example: Create user authentication patch
|
|
half_orm dev patch create 456-user-auth
|
|
|
|
# Creates ho-patch/456-user-auth branch
|
|
# Creates Patches/456-user-auth/ directory
|
|
```
|
|
|
|
### 3. Develop Your Changes
|
|
|
|
```bash
|
|
# Add SQL migration
|
|
echo "CREATE TABLE users (id SERIAL PRIMARY KEY, username TEXT);" > Patches/456-user-auth/1-create-users.sql
|
|
|
|
# Add Python migration (optional)
|
|
cat > Patches/456-user-auth/2-seed-data.py << 'EOF'
|
|
from ddd_domain.public.users import Users
|
|
|
|
def apply(model):
|
|
Users(username='admin').ho_insert()
|
|
EOF
|
|
|
|
# Apply patch to test database
|
|
half_orm dev patch apply
|
|
|
|
# Generated ORM classes available in ddd_domain/
|
|
from ddd_domain.public.users import Users
|
|
user = Users(username='john').ho_insert()
|
|
```
|
|
|
|
### 4. Test Your Changes
|
|
|
|
```bash
|
|
# Run tests (pytest must be configured)
|
|
pytest tests/
|
|
|
|
# half-orm-dev validates:
|
|
# - Patch SQL syntax
|
|
# - Patch idempotency (can be applied twice)
|
|
# - Test suite passes with full release context
|
|
```
|
|
|
|
### 5. Merge Patch into Release
|
|
|
|
```bash
|
|
# Merge patch (automatic validation + tests)
|
|
half_orm dev patch merge
|
|
|
|
# What happens:
|
|
# 1. Creates temp validation branch
|
|
# 2. Applies ALL staged patches + your patch
|
|
# 3. Runs pytest tests/
|
|
# 4. If tests pass → merges into ho-release/X.Y.Z
|
|
# 5. Changes patch status to "staged" in TOML
|
|
# 6. Deletes patch branch
|
|
```
|
|
|
|
### 6. Promote Release
|
|
|
|
```bash
|
|
# Stage → RC (first release candidate)
|
|
half_orm dev release promote rc
|
|
|
|
# Creates .hop/releases/0.17.0-rc1.txt snapshot
|
|
# Tags ho-release-0.17.0-rc1
|
|
|
|
# RC → Production (after validation)
|
|
half_orm dev release promote prod
|
|
|
|
# Merges into ho-prod branch
|
|
# Creates .hop/releases/0.17.0.txt
|
|
# Tags production-0.17.0
|
|
# Generates .hop/model/schema-0.17.0.sql
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 Common Commands
|
|
|
|
### Status & Information
|
|
|
|
```bash
|
|
half_orm dev check # Show repository state
|
|
```
|
|
|
|
### Patch Management
|
|
|
|
```bash
|
|
half_orm dev patch create # create a new patch for release
|
|
half_orm dev patch apply # Apply patch to dev database
|
|
half_orm dev patch merge # Integrate patch into release
|
|
```
|
|
|
|
### Release Management
|
|
|
|
```bash
|
|
half_orm dev release create <level> # Create release (patch/minor/major)
|
|
half_orm dev release promote rc # Stage → RC
|
|
half_orm dev release promote prod # RC → Production
|
|
```
|
|
|
|
### Production Deployment
|
|
|
|
```bash
|
|
# On production server
|
|
half_orm dev update # Check available releases
|
|
half_orm dev upgrade <version> # Deploy specific version
|
|
```
|
|
|
|
---
|
|
|
|
## 📁 Project Structure
|
|
|
|
```
|
|
ddd_domain/
|
|
├── .hop/ # half-orm-dev metadata
|
|
│ ├── config # Repository configuration
|
|
│ ├── model/ # Database schemas and data
|
|
│ │ ├── schema.sql # Current production schema (symlink)
|
|
│ │ ├── schema-X.Y.Z.sql # Versioned schemas
|
|
│ │ ├── metadata-X.Y.Z.sql # half_orm_meta data dumps
|
|
│ │ └── data-X.Y.Z.sql # Reference data from @HOP:data patches
|
|
│ └── releases/ # Release tracking files
|
|
│ ├── X.Y.Z-patches.toml # Development releases (mutable)
|
|
│ ├── X.Y.Z-rcN.txt # Release candidates (immutable)
|
|
│ └── X.Y.Z.txt # Production releases (immutable)
|
|
├── Patches/ # Patch directories
|
|
│ └── <id>-<description>/ # Individual patch files
|
|
│ ├── *.sql # SQL migrations (numbered)
|
|
│ └── *.py # Python migrations (optional)
|
|
├── ddd_domain/ # Generated ORM package
|
|
│ └── <schema>/ # schema classes
|
|
└── tests/ # Test suite (pytest)
|
|
```
|
|
|
|
---
|
|
|
|
## 🌿 Git Branch Structure
|
|
|
|
- **`ho-prod`**: Production branch (stable, source of truth)
|
|
- **`ho-release/X.Y.Z`**: Release integration branches (temporary)
|
|
- **`ho-patch/ID`**: Patch development branches (temporary)
|
|
|
|
All development happens on patch branches, merged into release branches, then promoted to production.
|
|
|
|
---
|
|
|
|
## 💾 Data Persistence (@HOP:data)
|
|
|
|
For reference data that must be loaded with every database installation (lookup tables, default roles, etc.), use the `@HOP:data` annotation:
|
|
|
|
```sql
|
|
-- @HOP:data
|
|
-- This file will be included in model/data-X.Y.Z.sql
|
|
|
|
INSERT INTO roles (name, description)
|
|
VALUES ('admin', 'Administrator')
|
|
ON CONFLICT (name) DO NOTHING;
|
|
|
|
INSERT INTO permissions (name)
|
|
VALUES ('read'), ('write'), ('delete')
|
|
ON CONFLICT DO NOTHING;
|
|
```
|
|
|
|
### How it works
|
|
|
|
1. **In patches**: SQL files starting with `-- @HOP:data` contain reference data
|
|
2. **Production promote**: All `@HOP:data` files are consolidated into `model/data-X.Y.Z.sql`
|
|
3. **Clone/Restore**: Data files are loaded automatically after schema restoration
|
|
4. **Production upgrade**: Data is inserted via normal patch application (no special handling)
|
|
|
|
### Best practices
|
|
|
|
- Use `ON CONFLICT DO NOTHING` or `ON CONFLICT DO UPDATE` for idempotency
|
|
- Keep data files small and focused (one concern per file)
|
|
- Number your SQL files to control execution order: `01_roles.sql`, `02_permissions.sql`
|
|
- Only use for **reference data**, not user-generated data
|
|
|
|
---
|
|
|
|
## ⚡ Async Usage
|
|
|
|
The generated package supports both synchronous and asynchronous access to the database.
|
|
|
|
### Sync
|
|
|
|
```python
|
|
from ddd_domain.public.users import Users
|
|
|
|
user = Users(username='john').ho_get()
|
|
users = list(Users(is_active=True).ho_select())
|
|
```
|
|
|
|
### Async
|
|
|
|
```python
|
|
import asyncio
|
|
from ddd_domain import aconnect, adisconnect
|
|
from ddd_domain.public.users import Users
|
|
|
|
async def main():
|
|
await aconnect()
|
|
try:
|
|
user = await Users(username='john').ho_aget()
|
|
users = await Users(is_active=True).ho_aselect()
|
|
finally:
|
|
await adisconnect()
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
### REST API (FastAPI)
|
|
|
|
```python
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
import ddd_domain
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
await ddd_domain.aconnect()
|
|
yield
|
|
await ddd_domain.adisconnect()
|
|
|
|
app = FastAPI(lifespan=lifespan)
|
|
```
|
|
|
|
The async connection pool is established automatically during tests via the `_async_pool`
|
|
fixture in `tests/conftest.py`.
|
|
|
|
---
|
|
|
|
## 📚 Documentation
|
|
|
|
- **half-orm-dev**: https://github.com/half-orm/half-orm-dev
|
|
- **half-orm**: https://github.com/half-orm/half-orm
|
|
- **Workflow guide**: https://github.com/half-orm/half-orm-dev#readme
|
|
|
|
---
|
|
|
|
## 🆘 Getting Help
|
|
|
|
```bash
|
|
half_orm dev --help # General help
|
|
half_orm dev patch --help # Patch commands
|
|
half_orm dev release --help # Release commands
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ Important Notes
|
|
|
|
1. **Always work on patch branches** - Never commit directly to ho-prod or ho-release
|
|
2. **Test before merging** - `patch merge` runs tests automatically
|
|
3. **Sequential releases** - Only the smallest version in preparation can be promoted
|
|
4. **Idempotent patches** - SQL must be replayable (use `IF NOT EXISTS`, etc.)
|
|
5. **Production schema** - `.hop/model/schema.sql` is the source of truth
|
|
|
|
---
|
|
|
|
Generated by half-orm-dev 1.0.0-a32
|