The login cache is shared by every mdrs process, but the refresh was
guarded by a lock that only reaches inside one. Concurrent runs each
sent the same refresh token, and a provider that rotates them accepts
the first and refuses the rest.
- hold a lock that spans processes across the whole read-refresh-
write, checking cheaply first so ordinary requests never take it
- write the cache through a temporary file: opening it for writing
truncates it, and a reader landing in that window found it empty
and threw the session away
- take the lock for every write, not just the refresh, so a login
running beside one cannot be silently reverted
- wait for a busy lock on Windows rather than giving up after the ten
attempts msvcrt allows, and retry the rename it refuses while a
reader still holds the file open
- bound the refresh request on its own, so a provider that goes quiet
cannot hold the lock indefinitely
- accept bare hostnames such as localhost, store URLs without the
trailing slash, and join download paths through one helper
Abstract the configuration storage mechanism to allow using custom
configurations, such as in-memory setups, when using the tool as
a library. This aligns the configuration architecture with the
session cache abstraction.
- Define ConfigInterface protocol and InMemoryConfig class
- Make CacheFile, InMemoryCache, ConfigFile, and InMemoryConfig
explicitly inherit their interfaces
- Update MdrsService and MdrsClient to accept customizable
config_class and config instances
- Add validation to check remote parameter consistency in
create_connection
- Remove unused imports across command files