| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| //! Predicted server-state mutations emitted by op modules on commit. |
| //! |
| //! Name-keyed throughout. Server emits empty reply bodies, so the |
| //! workload cannot recover server-assigned numeric ids; shadow lookups |
| //! address entities by name (`WireIdentifier::named`). Id-keyed effects |
| //! return once reply-body parsing lands. |
| |
| use server_common::sharding::IggyNamespace; |
| |
| #[derive(Debug, Clone)] |
| pub enum Effect { |
| None, |
| AddStream { |
| name: String, |
| }, |
| RemoveStream { |
| name: String, |
| }, |
| AddTopic { |
| stream: String, |
| name: String, |
| partitions: u32, |
| }, |
| RemoveTopic { |
| stream: String, |
| name: String, |
| }, |
| AddPartitions { |
| stream: String, |
| topic: String, |
| count: u32, |
| }, |
| RemovePartitions { |
| stream: String, |
| topic: String, |
| count: u32, |
| }, |
| AddUser { |
| name: String, |
| }, |
| RemoveUser { |
| name: String, |
| }, |
| AddPat { |
| name: String, |
| }, |
| RemovePat { |
| name: String, |
| }, |
| AddConsumerGroup { |
| stream: String, |
| topic: String, |
| name: String, |
| }, |
| RemoveConsumerGroup { |
| stream: String, |
| topic: String, |
| name: String, |
| }, |
| SendCommitted { |
| ns: IggyNamespace, |
| count: u64, |
| }, |
| OffsetStored { |
| key: (IggyNamespace, u8, u32), |
| value: u64, |
| }, |
| OffsetDeleted { |
| key: (IggyNamespace, u8, u32), |
| }, |
| RenameStream { |
| old: String, |
| new: String, |
| }, |
| RenameTopic { |
| stream: String, |
| old: String, |
| new: String, |
| }, |
| RenameUser { |
| old: String, |
| new: String, |
| /// Carries the current password through the rename so the |
| /// shadow re-keys `passwords` under `new` without loss. |
| password: String, |
| }, |
| /// Password rotated; shadow updates `passwords` so the next |
| /// `ChangePassword` sample reads the new value. |
| PasswordChanged { |
| user: String, |
| new_password: String, |
| }, |
| } |
| |
| /// Side-effects the driver must run against the simulator. Returned by |
| /// `Shadow::apply` so the auditor stays pure (no `&mut Simulator`). |
| #[derive(Debug, Clone)] |
| pub enum SimCommand { |
| /// Reserved hook: no op currently emits this. Will be wired when a |
| /// workload-driven namespace-creation op lands (today, namespaces are |
| /// pre-seeded by the test fixture via `Simulator::init_partition`). |
| InitPartition { ns: IggyNamespace }, |
| } |
| |
| #[derive(Debug, Clone)] |
| pub struct ApplyResult { |
| pub sim_commands: Vec<SimCommand>, |
| /// `true` when the shadow actually mutated; `false` when the effect |
| /// was a no-op (e.g. `AddTopic` after parent stream removed, or a |
| /// `Rename*` whose `old` key is gone). |
| pub applied: bool, |
| } |
| |
| impl Default for ApplyResult { |
| fn default() -> Self { |
| Self { |
| sim_commands: Vec::new(), |
| applied: true, |
| } |
| } |
| } |