fix(D.2b): harden optimistic-move pending map (Opus review I1+I2)
I2 (real bug): Clear() (teleport/logoff) and Remove() (item destroyed) now drop the item's _pendingMoves entry — a stale snapshot on a recycled guid could otherwise mis-rollback a different future item. I1 (race): track an OUTSTANDING count per item so an early ConfirmMove (0x0022) for the first of several in-flight moves of the SAME item can't clear the snapshot while a later move is unconfirmed — a later reject can still roll back to the original instead of stranding the item at the rejected position. Both with regression tests; full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8df395894e
commit
975f89c870
2 changed files with 49 additions and 8 deletions
|
|
@ -396,6 +396,32 @@ public sealed class ClientObjectTableTests
|
|||
public void RollbackMove_unknownItem_false()
|
||||
=> Assert.False(new ClientObjectTable().RollbackMove(0xDEADu));
|
||||
|
||||
[Fact]
|
||||
public void MoveItemOptimistic_twice_oneConfirm_stillRollsBack() // I1: an early confirm must not strand the item
|
||||
{
|
||||
var table = new ClientObjectTable();
|
||||
table.Ingest(FullWeenie(0x910u, container: 0xC0u)); table.MoveItem(0x910u, 0xC0u, 5);
|
||||
table.MoveItemOptimistic(0x910u, 0xC1u, 0); // move 1 (outstanding 1, snapshot C0/5)
|
||||
table.MoveItemOptimistic(0x910u, 0xC2u, 0); // move 2 (outstanding 2)
|
||||
table.ConfirmMove(0x910u); // server confirms move 1 → outstanding 1, STILL pending
|
||||
Assert.True(table.RollbackMove(0x910u)); // move 2 rejected → can still roll back (not stranded at C2)
|
||||
Assert.Equal(0xC0u, table.Get(0x910u)!.ContainerId);
|
||||
Assert.Equal(5, table.Get(0x910u)!.ContainerSlot);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_dropsPendingMoves_soRecycledGuidIsntMisRolledBack() // I2: pending must not survive a table flush
|
||||
{
|
||||
var table = new ClientObjectTable();
|
||||
table.Ingest(FullWeenie(0x911u, container: 0xC0u));
|
||||
table.MoveItemOptimistic(0x911u, 0xC1u, 0); // pending snapshot for 0x911
|
||||
table.Clear(); // teleport/logoff flushes the table
|
||||
|
||||
table.Ingest(FullWeenie(0x911u, container: 0xC5u)); // a recycled guid reappears fresh
|
||||
Assert.False(table.RollbackMove(0x911u)); // no stale pending → no mis-rollback
|
||||
Assert.Equal(0xC5u, table.Get(0x911u)!.ContainerId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainerIndex_SlotChange_ResortsInPlace() // guards the Reindex same-container early-out
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue