From 7f336200ea4e2f1fe6c5bd3a013e99d7025d816a Mon Sep 17 00:00:00 2001
From: Jason Volk <jason@zemos.net>
Date: Fri, 9 Mar 2018 07:42:28 -0800
Subject: [PATCH] ircd::server: Check and clear peer error after timeout.

---
 include/ircd/server/peer.h |  2 ++
 ircd/server.cc             | 30 ++++++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/ircd/server/peer.h b/include/ircd/server/peer.h
index 19d674d55..cb862078c 100644
--- a/include/ircd/server/peer.h
+++ b/include/ircd/server/peer.h
@@ -20,6 +20,7 @@ struct ircd::server::peer
 
 	static conf::item<size_t> link_min_default;
 	static conf::item<size_t> link_max_default;
+	static conf::item<seconds> error_clear_default;
 
 	net::remote remote;
 	std::list<link> links;
@@ -84,6 +85,7 @@ struct ircd::server::peer
 	string_view err_msg() const;
 	template<class... A> void err_set(A&&...);
 	void err_clear();
+	bool err_check();
 
 	// control panel
 	void interrupt();
diff --git a/ircd/server.cc b/ircd/server.cc
index 3dd5e64f1..c0695afac 100644
--- a/ircd/server.cc
+++ b/ircd/server.cc
@@ -363,14 +363,40 @@ const
 	return bool(e);
 }
 
+decltype(ircd::server::peer::error_clear_default)
+ircd::server::peer::error_clear_default
+{
+	{ "name",     "ircd.server.peer.error.clear_default" },
+	{ "default",  305L                                   }
+};
+
+bool
+ircd::server::peer::err_check()
+{
+	if(!ready)
+		return false;
+
+	if(!e)
+		return true;
+
+	//TODO: The specific error type should be switched and finer
+	//TODO: timeouts should be used depending on the error: i.e
+	//TODO: NXDOMAIN vs. temporary conn timeout, etc.
+	if(e->etime + seconds(error_clear_default) > now<steady_point>())
+		return false;
+
+	err_clear();
+	return true;
+}
+
 void
 ircd::server::peer::submit(request &request)
 try
 {
-	if(unlikely(!ready || !server::ready))
+	if(!err_check() || unlikely(!server::ready))
 		throw unavailable
 		{
-			"Peer is unable to take any requests."
+			"Peer is unable to take any requests: %s", err_msg()
 		};
 
 	link *const ret