D3: CarrierStore + LoadPortStore

Per-CARRIERID and per-PORTID stores wrap the D1 FSMs, mirroring the
ProcessJobStore / ExceptionStore pattern: heap-allocated state machines
keyed in a std::map, non-movable to keep this-capture lambdas safe,
synthetic create() that wires per-row change handlers into the store's
top-level callbacks.

CarrierStore:
  create(carrierid, port_id, capacity)  — default 25-slot map
  fire_id_event / fire_slot_map_event / fire_access_event
  set_id_handler / set_slot_map_handler / set_access_handler

LoadPortStore:
  create(port_id)
  associate(pid, carrierid) / disassociate(pid)
  fire_transfer_event / fire_reservation_event
  set_transfer_handler / set_reservation_handler / set_association_handler

Both join EquipmentDataModel alongside process_jobs / control_jobs /
exceptions.  Six test cases cover create-dedup, ID-status change
observation, slot-map / access independence, port association,
transfer lifecycle, and reservation handler firing.

Server-side dispatch (S3F17 -> CarrierStore::fire_id_event, S3F25 ->
LoadPortStore transfer) lands in D4.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 00:14:50 +02:00
parent 5f1444c756
commit 7668ceaae4
4 changed files with 306 additions and 0 deletions
+3
View File
@@ -1,6 +1,7 @@
#pragma once
#include "secsgem/gem/store/alarms.hpp"
#include "secsgem/gem/store/carriers.hpp"
#include "secsgem/gem/store/clock.hpp"
#include "secsgem/gem/store/control_jobs.hpp"
#include "secsgem/gem/store/equipment_constants.hpp"
@@ -36,6 +37,8 @@ struct EquipmentDataModel {
ProcessJobStore process_jobs;
ControlJobStore control_jobs;
ExceptionStore exceptions;
CarrierStore carriers;
LoadPortStore load_ports;
// Convenience: VID -> value lookup spanning SVIDs and DVIDs.
std::optional<s2::Item> vid_value(uint32_t vid) const {