diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 1af84cff5..b9076c047 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -45,7 +45,13 @@ RemoteStore::RemoteStore(const Params & params) , connections(make_ref>( std::max(1, (int) maxConnections), [this]() { return openConnectionWrapper(); }, - [](const ref & r) { return r->to.good() && r->from.good(); } + [this](const ref & r) { + return + r->to.good() + && r->from.good() + && std::chrono::duration_cast( + std::chrono::steady_clock::now() - r->startTime).count() < maxConnectionAge; + } )) { } @@ -106,6 +112,8 @@ ref UDSRemoteStore::openConnection() conn->from.fd = conn->fd.get(); conn->to.fd = conn->fd.get(); + conn->startTime = std::chrono::steady_clock::now(); + initConnection(*conn); return conn; @@ -619,6 +627,12 @@ void RemoteStore::connect() } +void RemoteStore::flushBadConnections() +{ + connections->flushBad(); +} + + RemoteStore::Connection::~Connection() { try { diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index e370e4797..30c6beae6 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -25,6 +25,9 @@ public: const Setting maxConnections{(Store*) this, 1, "max-connections", "maximum number of concurrent connections to the Nix daemon"}; + const Setting maxConnectionAge{(Store*) this, std::numeric_limits::max(), + "max-connection-age", "number of seconds to reuse a connection"}; + RemoteStore(const Params & params); /* Implementations of abstract store API methods. */ @@ -95,6 +98,8 @@ public: void connect() override; + void flushBadConnections(); + protected: struct Connection @@ -102,6 +107,7 @@ protected: FdSink to; FdSource from; unsigned int daemonVersion; + std::chrono::time_point startTime; virtual ~Connection(); diff --git a/src/libutil/pool.hh b/src/libutil/pool.hh index 703309002..0b142b059 100644 --- a/src/libutil/pool.hh +++ b/src/libutil/pool.hh @@ -168,6 +168,16 @@ public: { return state.lock()->max; } + + void flushBad() + { + auto state_(state.lock()); + std::vector> left; + for (auto & p : state_->idle) + if (validator(p)) + left.push_back(p); + std::swap(state_->idle, left); + } }; }