screeps icon indicating copy to clipboard operation
screeps copied to clipboard

Room setup and position layout not idempotent when cpu exhausted

Open sparr opened this issue 8 years ago • 5 comments

If a call to Room.setup() or Room.updatePosition() runs out of CPU, it will try to run again the next tick. Many of the operations here are not idempotent, leading to conflicts between things placed on the previous attempt and things placed on the current tick.

Partial solution 1) Keep track of setup/update progress on a room, and start over where we left off.

Partial solution 2) Track more info about some entries in room.memory.position such as the "target" of a link

Partial solution 3) Clear some room.memory.position arrays prior to pushing to them.

sparr avatar Sep 29 '17 17:09 sparr

Note that while implementing #1 you will run into problems with memory [de]serialization. Many steps of the current process expect the children of room.memory.position to contain RoomPosition objects, which is true the tick they are created but not the next tick. Later steps in the process will need to re-instanciate the objects rather than relying on them still being classed.

sparr avatar Sep 29 '17 17:09 sparr

I think this is related to #452

I think to make the different layout steps idempotent is a good step in the right direction.

I don't understand part 2, where this helps to make the process more robust.

In between I had a recursive solution to build the rooms, to be able to try multiple positions. E.g. if in the process it can't build all extensions it would go back to the pathStart and try another one. It was really tricky to handle all the variables in their respective state.

I think it would also be good to handle the CPU better. E.g. checking if we expect that the next operation is able to finish.

TooAngel avatar Sep 29 '17 21:09 TooAngel

Part 2 is necessary because a step might fail in the middle. For example, if the step for setting the storage position ever fails, we can always wipe out positions.storage and insert the new one. But if any step that creates a link fails, we can't wipe out positions.link because a different step (that isn't going to be re-run) might have already created some links.

If we kept track of what each link's purpose is (terminal, source, etc) then we would know which ones to remove after a failed step.

sparr avatar Sep 29 '17 22:09 sparr

K, got your point.

I'm not sure if the idempotent condition is enough requirement. Your example is a bit tricky, because only redoing the storage step will rarely work, the following steps are dependent on the storage position and have to be redone, too.

Having some 'savepoints' from where we can continue. Maybe even by intention, when claiming a room we do not necessarily need to calculate the lab, terminal and observer position, this can be done later, too

TooAngel avatar Oct 03 '17 19:10 TooAngel

Ideally, the storage step would work on its own even if the other steps have already been done, and would produce the same result each time it runs. There will be a storage-shaped hole in all the other steps' results, which is exactly where the storage step should put the storage if it runs idempotently.

Savepoints to continue from is a lesser but still useful step, and that would mostly be my #1 with a little of my #3.

I ran into a bug in my code recently where there was a sometimes-infinite loop in a helper function (maybe inPositions?) that caused arbitrary parts of the init/setup/update code to time out. I ended up adding a terrible savepoint system which I threw away and made this issue to prompt myself to eventually recreate.

sparr avatar Oct 03 '17 20:10 sparr