feat(triggers): surface name on the Trigger model (§4.5, step B-1)
Read the new `name` column through the data model: `Trigger`/`TriggerRow` carry it, every trigger SELECT/RETURNING includes it, and the row→Trigger assembly + the interactive create paths populate it (the create INSERTs still omit it, so they take the migration's default). Behavior unchanged — the apply diff still keys on the semantic tuple; B-2 switches it to name-keying (enabling Update) and wires the manifest. Tested: manager-core lib 367 + trigger journeys green; clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1445,7 +1445,13 @@ fn disabled_target_warnings(bundle: &Bundle) -> Vec<String> {
|
|||||||
if r.enabled && disabled.contains(r.script.as_str()) {
|
if r.enabled && disabled.contains(r.script.as_str()) {
|
||||||
out.push(format!(
|
out.push(format!(
|
||||||
"route `{}` is enabled but its script `{}` is disabled — it will 404",
|
"route `{}` is enabled but its script `{}` is disabled — it will 404",
|
||||||
route_key(r.method.as_deref(), r.host_kind, &r.host, r.path_kind, &r.path),
|
route_key(
|
||||||
|
r.method.as_deref(),
|
||||||
|
r.host_kind,
|
||||||
|
&r.host,
|
||||||
|
r.path_kind,
|
||||||
|
&r.path
|
||||||
|
),
|
||||||
r.script
|
r.script
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -1919,6 +1925,7 @@ mod tests {
|
|||||||
id: TriggerId::from(uuid::Uuid::new_v4()),
|
id: TriggerId::from(uuid::Uuid::new_v4()),
|
||||||
app_id: AppId::from(uuid::Uuid::nil()),
|
app_id: AppId::from(uuid::Uuid::nil()),
|
||||||
script_id,
|
script_id,
|
||||||
|
name: "t".into(),
|
||||||
kind,
|
kind,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: TriggerDispatchMode::Async,
|
dispatch_mode: TriggerDispatchMode::Async,
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ pub struct Trigger {
|
|||||||
pub id: TriggerId,
|
pub id: TriggerId,
|
||||||
pub app_id: AppId,
|
pub app_id: AppId,
|
||||||
pub script_id: ScriptId,
|
pub script_id: ScriptId,
|
||||||
|
/// §4.5 per-app trigger identifier; the manifest merge/upsert key.
|
||||||
|
pub name: String,
|
||||||
pub kind: TriggerKind,
|
pub kind: TriggerKind,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub dispatch_mode: TriggerDispatchMode,
|
pub dispatch_mode: TriggerDispatchMode,
|
||||||
@@ -735,7 +737,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'kv', TRUE, $3, $4, $5, $6, $7) \
|
) VALUES ($1, $2, 'kv', TRUE, $3, $4, $5, $6, $7) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -766,6 +768,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Kv,
|
kind: TriggerKind::Kv,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -800,7 +803,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'docs', TRUE, $3, $4, $5, $6, $7) \
|
) VALUES ($1, $2, 'docs', TRUE, $3, $4, $5, $6, $7) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -831,6 +834,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Docs,
|
kind: TriggerKind::Docs,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -863,7 +867,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'dead_letter', TRUE, 'async', 1, 'constant', 0, $3) \
|
) VALUES ($1, $2, 'dead_letter', TRUE, 'async', 1, 'constant', 0, $3) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -891,6 +895,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::DeadLetter,
|
kind: TriggerKind::DeadLetter,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -927,7 +932,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'cron', TRUE, $3, $4, $5, $6, $7) \
|
) VALUES ($1, $2, 'cron', TRUE, $3, $4, $5, $6, $7) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -957,6 +962,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Cron,
|
kind: TriggerKind::Cron,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -992,7 +998,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'files', TRUE, $3, $4, $5, $6, $7) \
|
) VALUES ($1, $2, 'files', TRUE, $3, $4, $5, $6, $7) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -1023,6 +1029,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Files,
|
kind: TriggerKind::Files,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -1056,7 +1063,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'pubsub', TRUE, $3, $4, $5, $6, $7) \
|
) VALUES ($1, $2, 'pubsub', TRUE, $3, $4, $5, $6, $7) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -1084,6 +1091,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Pubsub,
|
kind: TriggerKind::Pubsub,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -1116,7 +1124,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'email', TRUE, 'async', 3, 'exponential', 1000, $3) \
|
) VALUES ($1, $2, 'email', TRUE, 'async', 3, 'exponential', 1000, $3) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -1143,6 +1151,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Email,
|
kind: TriggerKind::Email,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -1185,7 +1194,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
|
|
||||||
async fn list_for_app(&self, app_id: AppId) -> Result<Vec<Trigger>, TriggerRepoError> {
|
async fn list_for_app(&self, app_id: AppId) -> Result<Vec<Trigger>, TriggerRepoError> {
|
||||||
let parents: Vec<TriggerRow> = sqlx::query_as(
|
let parents: Vec<TriggerRow> = sqlx::query_as(
|
||||||
"SELECT id, app_id, script_id, kind, enabled, dispatch_mode, \
|
"SELECT id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at \
|
registered_by_principal, created_at, updated_at \
|
||||||
FROM triggers WHERE app_id = $1 ORDER BY created_at DESC",
|
FROM triggers WHERE app_id = $1 ORDER BY created_at DESC",
|
||||||
@@ -1213,7 +1222,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
|
|
||||||
async fn get(&self, id: TriggerId) -> Result<Option<Trigger>, TriggerRepoError> {
|
async fn get(&self, id: TriggerId) -> Result<Option<Trigger>, TriggerRepoError> {
|
||||||
let parent: Option<TriggerRow> = sqlx::query_as(
|
let parent: Option<TriggerRow> = sqlx::query_as(
|
||||||
"SELECT id, app_id, script_id, kind, enabled, dispatch_mode, \
|
"SELECT id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at \
|
registered_by_principal, created_at, updated_at \
|
||||||
FROM triggers WHERE id = $1",
|
FROM triggers WHERE id = $1",
|
||||||
@@ -1463,7 +1472,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal \
|
registered_by_principal \
|
||||||
) VALUES ($1, $2, 'queue', TRUE, $3, $4, $5, $6, $7) \
|
) VALUES ($1, $2, 'queue', TRUE, $3, $4, $5, $6, $7) \
|
||||||
RETURNING id, app_id, script_id, kind, enabled, dispatch_mode, \
|
RETURNING id, app_id, script_id, name, kind, enabled, dispatch_mode, \
|
||||||
retry_max_attempts, retry_backoff, retry_base_ms, \
|
retry_max_attempts, retry_backoff, retry_base_ms, \
|
||||||
registered_by_principal, created_at, updated_at",
|
registered_by_principal, created_at, updated_at",
|
||||||
)
|
)
|
||||||
@@ -1494,6 +1503,7 @@ impl TriggerRepo for PostgresTriggerRepo {
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name.clone(),
|
||||||
kind: TriggerKind::Queue,
|
kind: TriggerKind::Queue,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -1700,6 +1710,7 @@ async fn hydrate_one(pool: &PgPool, parent: TriggerRow) -> Result<Trigger, Trigg
|
|||||||
id: parent.id.into(),
|
id: parent.id.into(),
|
||||||
app_id: parent.app_id.into(),
|
app_id: parent.app_id.into(),
|
||||||
script_id: parent.script_id.into(),
|
script_id: parent.script_id.into(),
|
||||||
|
name: parent.name,
|
||||||
kind,
|
kind,
|
||||||
enabled: parent.enabled,
|
enabled: parent.enabled,
|
||||||
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
dispatch_mode: dispatch_from_str(&parent.dispatch_mode),
|
||||||
@@ -1742,6 +1753,7 @@ struct TriggerRow {
|
|||||||
id: Uuid,
|
id: Uuid,
|
||||||
app_id: Uuid,
|
app_id: Uuid,
|
||||||
script_id: Uuid,
|
script_id: Uuid,
|
||||||
|
name: String,
|
||||||
kind: String,
|
kind: String,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
dispatch_mode: String,
|
dispatch_mode: String,
|
||||||
|
|||||||
@@ -892,6 +892,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: crate::trigger_repo::TriggerKind::Kv,
|
kind: crate::trigger_repo::TriggerKind::Kv,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: req.dispatch_mode,
|
dispatch_mode: req.dispatch_mode,
|
||||||
@@ -920,6 +921,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: crate::trigger_repo::TriggerKind::Docs,
|
kind: crate::trigger_repo::TriggerKind::Docs,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: req.dispatch_mode,
|
dispatch_mode: req.dispatch_mode,
|
||||||
@@ -948,6 +950,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: crate::trigger_repo::TriggerKind::DeadLetter,
|
kind: crate::trigger_repo::TriggerKind::DeadLetter,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: TriggerDispatchMode::Async,
|
dispatch_mode: TriggerDispatchMode::Async,
|
||||||
@@ -977,6 +980,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: TriggerKind::Email,
|
kind: TriggerKind::Email,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: TriggerDispatchMode::Async,
|
dispatch_mode: TriggerDispatchMode::Async,
|
||||||
@@ -1021,6 +1025,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: crate::trigger_repo::TriggerKind::Cron,
|
kind: crate::trigger_repo::TriggerKind::Cron,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: req.dispatch_mode,
|
dispatch_mode: req.dispatch_mode,
|
||||||
@@ -1050,6 +1055,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: crate::trigger_repo::TriggerKind::Files,
|
kind: crate::trigger_repo::TriggerKind::Files,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: req.dispatch_mode,
|
dispatch_mode: req.dispatch_mode,
|
||||||
@@ -1078,6 +1084,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: crate::trigger_repo::TriggerKind::Pubsub,
|
kind: crate::trigger_repo::TriggerKind::Pubsub,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: req.dispatch_mode,
|
dispatch_mode: req.dispatch_mode,
|
||||||
@@ -1154,6 +1161,7 @@ mod tests {
|
|||||||
id,
|
id,
|
||||||
app_id,
|
app_id,
|
||||||
script_id: req.script_id,
|
script_id: req.script_id,
|
||||||
|
name: "mock".into(),
|
||||||
kind: TriggerKind::Queue,
|
kind: TriggerKind::Queue,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dispatch_mode: req.dispatch_mode,
|
dispatch_mode: req.dispatch_mode,
|
||||||
|
|||||||
Reference in New Issue
Block a user