Class: Carson::Courier
- Inherits:
-
Object
- Object
- Carson::Courier
- Defined in:
- lib/carson/courier.rb
Overview
The delivery person — picks up parcels and delivers them to the registry.
The courier is a Carson employee assigned to a warehouse. They pick up a parcel, ship it to the bureau, file a waybill, and wait at the registry while the bureaucrats check it.
The courier is a thin orchestrator: it creates a Waybill and sends it messages. The domain logic lives in the objects, not the courier.
The bureau
The bureau is a registry (GitHub) where bureaucrats work. They check parcels (CI, review, mergeability) and either accept them into the registry or hold them with a reason.
Situations the courier encounters
Each numbered situation is handled by a specific guard or branch in the delivery flow. The number appears in the code comment where it’s handled.
01. Parcel on main — cannot deliver from the destination.
02. Parcel behind standard — not based on client's latest standard.
03. Shipping fails — warehouse couldn't push to the bureau.
04. Waybill filing fails — bureau rejected the paperwork.
05. Pending at registry — bureaucrats still checking (CI running).
06. Failed at registry — bureaucrats rejected (CI failed).
07. Review pending — review still in progress.
08. Review changes requested — reviewer wants corrections.
09. Merge conflict — parcel conflicts with registry contents.
10. Behind standard (post-filing) — standard changed since shipping.
11. Policy block — bureau regulation prevents acceptance.
12. Draft waybill — form not finalised.
13. Mergeability pending — bureau still processing eligibility.
14. Acceptance succeeds — parcel enters the registry. Delivered.
15. Acceptance fails — classify why, report.
16. Bureau unreachable — cannot contact the bureau.
17. Parcel already delivered — already in registry.
18. Waybill closed — cancelled by someone externally.
Design: wait and poll at the registry
The courier waits at the registry while the bureaucrats check the parcel. It polls up to MAX_CHECKS_AT_REGISTRY times, pausing between each check. If the bureaucrats give a definitive answer (accepted or rejected), the courier acts immediately. If the checks are exhausted without a definitive answer, the courier reports “filed” — the parcel is still at the registry.
Future: destination modes
Currently remote-centred (ship → waybill → registry → acceptance). A future local-centred mode merges locally; remote is a synced backup. The destination mode should be injectable, not baked in.
Constant Summary collapse
- OK =
Exit codes — shared contract between Carson employees and the CLI.
0- ERROR =
1- BLOCKED =
2- MAX_CHECKS_AT_REGISTRY =
The courier checks the registry up to 6 times before leaving.
6
Instance Method Summary collapse
-
#deliver(parcel, title: nil, body_file: nil, commit_message: nil) ⇒ Object
Deliver a parcel to the registry.
-
#initialize(warehouse, ledger: nil, merge_method: "rebase", poll_interval_at_registry: 30) ⇒ Courier
constructor
A new instance of Courier.
Constructor Details
#initialize(warehouse, ledger: nil, merge_method: "rebase", poll_interval_at_registry: 30) ⇒ Courier
Returns a new instance of Courier.
64 65 66 67 68 69 |
# File 'lib/carson/courier.rb', line 64 def initialize( warehouse, ledger: nil, merge_method: "rebase", poll_interval_at_registry: 30 ) @warehouse = warehouse @ledger = ledger @merge_method = merge_method @poll_interval_at_registry = poll_interval_at_registry end |
Instance Method Details
#deliver(parcel, title: nil, body_file: nil, commit_message: nil) ⇒ Object
Deliver a parcel to the registry. Ships it, files a waybill, waits at the registry for the bureaucrats.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/carson/courier.rb', line 73 def deliver( parcel, title: nil, body_file: nil, commit_message: nil ) result = { command: "deliver", label: parcel.label, remote_main: "#{@warehouse.bureau_address}/#{@warehouse.main_label}" } # 01. Parcel on main — cannot deliver from the destination. if parcel.on_main?( @warehouse.main_label ) return blocked( result, "cannot deliver from #{@warehouse.main_label}", recovery: "carson worktree create <name>" ) end # Dirty tree guard — the warehouse knows if its floor is clean. if && @warehouse.clean? return blocked( result, "working tree is already clean", recovery: "carson deliver" ) end if ! && !@warehouse.clean? return blocked( result, "working tree is dirty", recovery: "carson deliver --commit \"describe this delivery\"" ) end # Submit compliance — ensure templates are in sync before delivery. compliance = @warehouse.submit_compliance! unless compliance[ :compliant ] return error( result, compliance[ :error ] || "compliance check failed" ) end # Pack the parcel if the sender provided a commit message. # Skip if compliance already committed everything (tree is now clean). if && !@warehouse.clean? unless @warehouse.pack!( message: ) return error( result, "packing failed — nothing to commit?" ) end end # Refresh parcel head — compliance or pack may have created commits. parcel = Parcel.new( label: parcel.label, head: @warehouse.current_head, shelf: parcel.shelf ) # 02. Parcel behind standard — not based on client's latest standard. @warehouse.fetch_latest( registry: @warehouse.main_label ) unless @warehouse.based_on_latest_standard?( parcel ) remote_main = "#{@warehouse.bureau_address}/#{@warehouse.main_label}" return blocked( result, "branch is behind #{remote_main}", recovery: "git rebase #{remote_main}, then carson deliver" ) end # The courier picks up the parcel — start tracking. record( parcel, status: "preparing", summary: "delivery accepted" ) # 03. Shipping fails — warehouse couldn't push to the bureau. unless @warehouse.ship( parcel ) return error( result, "push failed" ) end # File a waybill with the bureau. waybill = Waybill.new( label: parcel.label, warehouse_path: @warehouse.path ) waybill.file!( title: title, body_file: body_file ) # 04. Waybill filing fails — bureau rejected the paperwork. unless waybill.filed? return error( result, "PR creation failed", recovery: "carson deliver" ) end result[ :tracking_number ] = waybill.tracking_number result[ :url ] = waybill.url # Wait at the registry while the bureaucrats check the parcel. wait_and_poll_at_registry( waybill, result ) # Update the ledger with the final outcome. record( parcel, status: result[ :outcome ] || "filed", summary: result[ :hold_reason ] ) result[ :exit ] ||= OK result end |