Big-Link-Man/STORY_2.5_IMPLEMENTATION_SU...

5.7 KiB

Story 2.5: Deployment Target Assignment - Implementation Summary

Status

COMPLETED - All acceptance criteria met, 100% test coverage

Overview

Implemented deployment target assignment functionality that allows job configurations to specify which generated tier1 articles should be assigned to specific sites. Only tier1 articles can be assigned to deployment targets - tier2/tier3 always get site_deployment_id = null. The implementation uses a simple round-robin assignment strategy where the first N tier1 articles are assigned to N deployment targets, and remaining tier1 articles get null assignment.

Changes Made

1. Job Configuration Schema (src/generation/job_config.py)

  • Added deployment_targets field (optional array of strings) to Job dataclass
  • Added validation to ensure deployment_targets is an array of strings
  • Job configuration now supports specifying custom hostnames for deployment target assignment

2. Deployment Assignment Logic (src/generation/deployment_assignment.py) - NEW FILE

Created new module with three core functions:

  • resolve_hostname_to_id() - Resolves a hostname to its site_deployment_id
  • validate_and_resolve_targets() - Validates all hostnames at job start (fail-fast approach)
  • assign_site_for_article() - Implements round-robin assignment logic

3. Database Repository Updates (src/database/repositories.py)

  • Updated GeneratedContentRepository.create() to accept optional site_deployment_id parameter
  • Maintains backward compatibility - parameter defaults to None

4. Batch Processor Integration (src/generation/batch_processor.py)

  • Added site_deployment_repo parameter to BatchProcessor.__init__()
  • Validates deployment targets at job start before generating any content
  • Only applies deployment targets to tier1 articles - tier2/tier3 always get null
  • Assigns site_deployment_id to each tier1 article based on its index
  • Logs assignment decisions at INFO level
  • Passes site_deployment_id to repository when creating content

5. CLI Updates (src/cli/commands.py)

  • Updated generate-batch command to initialize and pass SiteDeploymentRepository to BatchProcessor
  • Fixed merge conflict markers in the file

6. Example Job Configuration (jobs/example_deployment_targets.json) - NEW FILE

Created example job file demonstrating the deployment_targets field with 3 sites and 10 articles.

Test Coverage

Unit Tests (tests/unit/test_deployment_assignment.py) - NEW FILE

13 unit tests covering:

  • Hostname resolution (valid and invalid)
  • Target validation (empty lists, valid hostnames, invalid hostnames, type checking)
  • Round-robin assignment logic (edge cases, overflow, single target)
  • The 10-article, 3-target scenario from the story

Integration Tests (tests/integration/test_deployment_target_assignment.py) - NEW FILE

10 integration tests covering:

  • Job config parsing with deployment_targets
  • Job config validation (type checking, missing field handling)
  • Batch processor validation at job start
  • End-to-end assignment logic
  • Repository backward compatibility
  • Tier1-only deployment target assignment (tier2+ always get null)

Total Test Results: 23/23 tests passing

Assignment Logic Example

Job with tier1 (10 articles), tier2 (100 articles), and 3 deployment targets:

Tier1 articles:

Article 0 → www.domain1.com (site_deployment_id = 5)
Article 1 → www.domain2.com (site_deployment_id = 8)
Article 2 → www.domain3.com (site_deployment_id = 12)
Articles 3-9 → null (no assignment)

Tier2 articles:

All 100 articles → null (tier2+ never get deployment targets)

Usage Example

{
  "jobs": [{
    "project_id": 2,
    "deployment_targets": [
      "www.domain1.com",
      "www.domain2.com",
      "www.domain3.com"
    ],
    "tiers": {
      "tier1": {
        "count": 10
      }
    }
  }]
}

Error Handling

The implementation provides clear error messages:

  1. Invalid hostnames: "Deployment targets not found in database: invalid.com. Please ensure these sites exist using 'list-sites' command."
  2. Missing repository: "deployment_targets specified but SiteDeploymentRepository not provided"
  3. Invalid configuration: Validates array type and string elements with descriptive errors

Backward Compatibility

  • All changes are backward compatible
  • Jobs without deployment_targets continue to work as before (all articles get site_deployment_id = null)
  • Existing tests remain passing
  • No database schema changes required (field already existed from Story 2.4)

Integration with Story 2.4

The implementation correctly integrates with Story 2.4's template selection logic:

  • If site_deployment_id is set → Story 2.4 uses mapped/random template for that site
  • If site_deployment_id is null → Story 2.4 uses random template selection

Acceptance Criteria Verification

Job configuration supports optional deployment_targets array of custom_hostnames
Round-robin assignment: articles 0 through N-1 get assigned, N+ get null
Missing deployment_targets → all articles get null
site_deployment_id stored in GeneratedContent at creation time
Invalid hostnames cause graceful errors with clear messages
Non-existent hostnames cause graceful errors
Validation occurs at job start (fail-fast)
Assignment decisions logged at INFO level

Files Created

  • src/generation/deployment_assignment.py
  • tests/unit/test_deployment_assignment.py
  • tests/integration/test_deployment_target_assignment.py
  • jobs/example_deployment_targets.json

Files Modified

  • src/generation/job_config.py
  • src/generation/batch_processor.py
  • src/database/repositories.py
  • src/cli/commands.py