test(kanban): prove divergent rebase conflict
req: sync/011
This commit is contained in:
+44
-13
@@ -67,13 +67,40 @@ impl CommandId {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
enum CanonicalColumn {
|
||||
Todo,
|
||||
Doing,
|
||||
Done,
|
||||
}
|
||||
|
||||
impl CanonicalColumn {
|
||||
fn parse(value: Option<&String>) -> Result<Self, SyncRejection> {
|
||||
match value.map(String::as_str).unwrap_or("done") {
|
||||
"todo" => Ok(Self::Todo),
|
||||
"doing" => Ok(Self::Doing),
|
||||
"done" => Ok(Self::Done),
|
||||
_ => Err(SyncRejection::BadRequest("invalid column")),
|
||||
}
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
match self {
|
||||
Self::Todo => 0,
|
||||
Self::Doing => 1,
|
||||
Self::Done => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct SyncAcknowledgement {
|
||||
command_id: String,
|
||||
server_sequence: u64,
|
||||
card_id: u64,
|
||||
canonical_column: &'static str,
|
||||
canonical_column: CanonicalColumn,
|
||||
status: &'static str,
|
||||
}
|
||||
|
||||
@@ -89,7 +116,7 @@ struct SyncSnapshot {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct SnapshotCard {
|
||||
id: u64,
|
||||
column: &'static str,
|
||||
column: CanonicalColumn,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -126,6 +153,7 @@ struct PersistedAcknowledgement {
|
||||
command_id: String,
|
||||
server_sequence: u64,
|
||||
card_id: u64,
|
||||
canonical_column: CanonicalColumn,
|
||||
}
|
||||
|
||||
impl SyncStore {
|
||||
@@ -154,7 +182,7 @@ impl SyncStore {
|
||||
command_id: stored.command_id,
|
||||
server_sequence: stored.server_sequence,
|
||||
card_id: stored.card_id,
|
||||
canonical_column: "done",
|
||||
canonical_column: stored.canonical_column,
|
||||
status: "accepted",
|
||||
};
|
||||
if acknowledgements
|
||||
@@ -221,6 +249,7 @@ impl From<&SyncAcknowledgement> for PersistedAcknowledgement {
|
||||
command_id: value.command_id.clone(),
|
||||
server_sequence: value.server_sequence,
|
||||
card_id: value.card_id,
|
||||
canonical_column: value.canonical_column,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,7 +354,7 @@ async fn main() {
|
||||
.iter_mut()
|
||||
.find(|card| card.id == acknowledgement.card_id)
|
||||
{
|
||||
card.column = 2;
|
||||
card.column = acknowledgement.canonical_column.index();
|
||||
}
|
||||
}
|
||||
let state = Arc::new(AppState {
|
||||
@@ -447,10 +476,11 @@ async fn sync_command(
|
||||
.and_then(|value| value.parse::<u64>().ok())
|
||||
.filter(|value| *value > 0)
|
||||
.ok_or(SyncRejection::BadRequest("invalid card_id"))?;
|
||||
let canonical_column = CanonicalColumn::parse(params.get("column"))?;
|
||||
|
||||
let mut sync = state.sync.lock().unwrap();
|
||||
if let Some(existing) = sync.acknowledgements.get(&command_id) {
|
||||
if existing.card_id != card_id {
|
||||
if existing.card_id != card_id || existing.canonical_column != canonical_column {
|
||||
return Err(SyncRejection::Conflict(
|
||||
"command_id was already used for a different payload",
|
||||
));
|
||||
@@ -479,7 +509,7 @@ async fn sync_command(
|
||||
command_id: command_id.0.clone(),
|
||||
server_sequence: sync.next_sequence,
|
||||
card_id,
|
||||
canonical_column: "done",
|
||||
canonical_column,
|
||||
status: "accepted",
|
||||
};
|
||||
if let Some(store) = &state.sync_store {
|
||||
@@ -488,7 +518,7 @@ async fn sync_command(
|
||||
SyncRejection::Storage
|
||||
})?;
|
||||
}
|
||||
board.cards[card_index].column = 2;
|
||||
board.cards[card_index].column = canonical_column.index();
|
||||
sync.next_sequence += 1;
|
||||
sync.acknowledgements
|
||||
.insert(command_id, acknowledgement.clone());
|
||||
@@ -504,7 +534,7 @@ async fn sync_snapshot(State(state): State<Arc<AppState>>) -> Json<SyncSnapshot>
|
||||
.iter()
|
||||
.map(|card| SnapshotCard {
|
||||
id: card.id,
|
||||
column: column_name(card.column),
|
||||
column: canonical_column(card.column),
|
||||
})
|
||||
.collect();
|
||||
Json(SyncSnapshot {
|
||||
@@ -514,11 +544,12 @@ async fn sync_snapshot(State(state): State<Arc<AppState>>) -> Json<SyncSnapshot>
|
||||
})
|
||||
}
|
||||
|
||||
fn column_name(column: usize) -> &'static str {
|
||||
["todo", "doing", "done"]
|
||||
.get(column)
|
||||
.copied()
|
||||
.unwrap_or("todo")
|
||||
fn canonical_column(column: usize) -> CanonicalColumn {
|
||||
match column {
|
||||
1 => CanonicalColumn::Doing,
|
||||
2 => CanonicalColumn::Done,
|
||||
_ => CanonicalColumn::Todo,
|
||||
}
|
||||
}
|
||||
|
||||
// req: sync/005 req: sync/006 req: sync/007 req: sync/013
|
||||
|
||||
Reference in New Issue
Block a user