mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 10:25:47 +02:00
feat(server): adding version monitoring task (#586)
feat(server): adding version monoitoring task Signed-off-by: Boaz Sade <boaz@dragonflydb.io> Signed-off-by: Boaz Sade <boaz@dragonflydb.io>
This commit is contained in:
parent
bbc809a637
commit
8d86e9b014
3 changed files with 124 additions and 4 deletions
2
helio
2
helio
|
@ -1 +1 @@
|
||||||
Subproject commit 12d2da75afbcfc8bbb5693180a6135abb8ba8d54
|
Subproject commit af5e0533c1adfb45f5fa3e6c93f5dfa1fde98360
|
|
@ -21,7 +21,7 @@ add_library(dragonfly_lib channel_slice.cc command_registry.cc
|
||||||
zset_family.cc version.cc bitops_family.cc container_utils.cc
|
zset_family.cc version.cc bitops_family.cc container_utils.cc
|
||||||
serializer_commons.cc journal/serializer.cc journal/executor.cc)
|
serializer_commons.cc journal/serializer.cc journal/executor.cc)
|
||||||
|
|
||||||
cxx_link(dragonfly_lib dfly_transaction dfly_facade redis_lib strings_lib html_lib
|
cxx_link(dragonfly_lib dfly_transaction dfly_facade redis_lib strings_lib html_lib http_client_lib
|
||||||
absl::random_random TRDP::jsoncons zstd TRDP::lz4)
|
absl::random_random TRDP::jsoncons zstd TRDP::lz4)
|
||||||
|
|
||||||
add_library(dfly_test_lib test_utils.cc)
|
add_library(dfly_test_lib test_utils.cc)
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <mimalloc.h>
|
#include <mimalloc.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include "base/init.h"
|
#include "base/init.h"
|
||||||
#include "base/proc_util.h" // for GetKernelVersion
|
#include "base/proc_util.h" // for GetKernelVersion
|
||||||
#include "facade/dragonfly_listener.h"
|
#include "facade/dragonfly_listener.h"
|
||||||
|
@ -28,6 +30,7 @@
|
||||||
#include "strings/human_readable.h"
|
#include "strings/human_readable.h"
|
||||||
#include "util/accept_server.h"
|
#include "util/accept_server.h"
|
||||||
#include "util/epoll/epoll_pool.h"
|
#include "util/epoll/epoll_pool.h"
|
||||||
|
#include "util/http/http_client.h"
|
||||||
#include "util/uring/uring_pool.h"
|
#include "util/uring/uring_pool.h"
|
||||||
#include "util/varz.h"
|
#include "util/varz.h"
|
||||||
|
|
||||||
|
@ -85,6 +88,9 @@ ABSL_FLAG(MaxMemoryFlag, maxmemory, MaxMemoryFlag(0),
|
||||||
"0 - means the program will automatically determine its maximum memory usage. "
|
"0 - means the program will automatically determine its maximum memory usage. "
|
||||||
"default: 0");
|
"default: 0");
|
||||||
|
|
||||||
|
ABSL_FLAG(bool, version_check, true,
|
||||||
|
"If true, Will monitor for new releases on Dragonfly servers once a day.");
|
||||||
|
|
||||||
using namespace util;
|
using namespace util;
|
||||||
using namespace facade;
|
using namespace facade;
|
||||||
using namespace io;
|
using namespace io;
|
||||||
|
@ -96,6 +102,117 @@ namespace dfly {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using util::http::TlsClient;
|
||||||
|
|
||||||
|
const std::string_view kInvalidVersion{"unknown version"};
|
||||||
|
|
||||||
|
std::string GetVersionString(const std::string& from) {
|
||||||
|
// The server sends a message such as {"latest": "0.12.0"}
|
||||||
|
const auto reg_match_expr = R"(\{\"latest"\:[ \t]*\"([0-9]+\.[0-9]+\.[0-9]+)\"\})";
|
||||||
|
VLOG(1) << "checking version '" << from << "'";
|
||||||
|
auto const regex = std::regex(reg_match_expr);
|
||||||
|
std::smatch match;
|
||||||
|
if (std::regex_match(from, match, regex) && match.size() > 1) {
|
||||||
|
// the second entry is the match to the group that holds the version string
|
||||||
|
return match[1].str();
|
||||||
|
} else {
|
||||||
|
return std::string{kInvalidVersion};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetRemoteVersion(ProactorBase* proactor, SSL_CTX* ssl_context, const std::string host,
|
||||||
|
std::string_view service, const std::string& resource,
|
||||||
|
const std::string& ver_header) {
|
||||||
|
namespace bh = boost::beast::http;
|
||||||
|
using ResponseType = bh::response<bh::string_body>;
|
||||||
|
|
||||||
|
bh::request<bh::string_body> req{bh::verb::get, resource, 11 /*http 1.1*/};
|
||||||
|
req.set(bh::field::host, host);
|
||||||
|
req.set(bh::field::user_agent, ver_header);
|
||||||
|
ResponseType res;
|
||||||
|
TlsClient http_client{proactor};
|
||||||
|
http_client.set_connect_timeout_ms(2000);
|
||||||
|
|
||||||
|
auto ec = http_client.Connect(host, service, ssl_context);
|
||||||
|
if (!ec) {
|
||||||
|
ec = http_client.Send(req, &res);
|
||||||
|
if (!ec) {
|
||||||
|
VLOG(1) << "successfully got response from HTTP GET for host " << host << ":" << service
|
||||||
|
<< "/" << resource << " response code is " << res.result();
|
||||||
|
|
||||||
|
if (res.result() == bh::status::ok) {
|
||||||
|
return GetVersionString(res.body());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VLOG(1) << "failed to process send HTTP GET to " << host << "@" << service << " at resource '"
|
||||||
|
<< resource << "', error: " << ec.message();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VLOG(1) << "failed to connect: " << ec.message();
|
||||||
|
}
|
||||||
|
return std::string{kInvalidVersion};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VersionMonitor {
|
||||||
|
fibers_ext::Fiber version_fiber_;
|
||||||
|
fibers_ext::Done monitor_ver_done_;
|
||||||
|
|
||||||
|
void Run(ProactorPool* proactor_pool) {
|
||||||
|
if (GetFlag(FLAGS_version_check)) {
|
||||||
|
version_fiber_ = proactor_pool->GetNextProactor()->LaunchFiber([this] { RunTask(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() {
|
||||||
|
monitor_ver_done_.Notify();
|
||||||
|
if (version_fiber_.IsJoinable()) {
|
||||||
|
version_fiber_.Join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RunTask();
|
||||||
|
};
|
||||||
|
|
||||||
|
void VersionMonitor::RunTask() {
|
||||||
|
const auto loop_sleep_time = std::chrono::hours(24); // every 24 hours
|
||||||
|
|
||||||
|
const std::string host_name = "version.dragonflydb.io";
|
||||||
|
const std::string_view port = "443";
|
||||||
|
const std::string resource = "/v1";
|
||||||
|
const std::string dev_version_name = "dev";
|
||||||
|
const std::string version_header = std::string("DragonflyDB/") + kGitTag;
|
||||||
|
|
||||||
|
// Don't run in dev environment - i.e. where we don't build with
|
||||||
|
// real version number
|
||||||
|
if (kGitTag == dev_version_name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX* context = TlsClient::CreateSslContext();
|
||||||
|
if (!context) {
|
||||||
|
VLOG(1) << "failed to create SSL context - cannot run version monitoring";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProactorBase* my_pb = ProactorBase::me();
|
||||||
|
while (true) {
|
||||||
|
const std::string remote_version =
|
||||||
|
GetRemoteVersion(my_pb, context, host_name, port, resource, version_header);
|
||||||
|
|
||||||
|
if (remote_version != kGitTag) {
|
||||||
|
LOG_FIRST_N(INFO, 1) << "Your current version '" << kGitTag
|
||||||
|
<< "' is not the latest version. A newer version '" << remote_version
|
||||||
|
<< "' is now available. Please consider an update.";
|
||||||
|
}
|
||||||
|
if (monitor_ver_done_.WaitFor(loop_sleep_time)) {
|
||||||
|
TlsClient::FreeContext(context);
|
||||||
|
VLOG(1) << "finish running version monitor task";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class TermColor { kDefault, kRed, kGreen, kYellow };
|
enum class TermColor { kDefault, kRed, kGreen, kYellow };
|
||||||
// Returns the ANSI color code for the given color. TermColor::kDefault is
|
// Returns the ANSI color code for the given color. TermColor::kDefault is
|
||||||
// an invalid input.
|
// an invalid input.
|
||||||
|
@ -195,9 +312,12 @@ bool RunEngine(ProactorPool* pool, AcceptServer* acceptor) {
|
||||||
acceptor->AddListener(mc_port, new Listener{Protocol::MEMCACHE, &service});
|
acceptor->AddListener(mc_port, new Listener{Protocol::MEMCACHE, &service});
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptor->Run();
|
VersionMonitor version_monitor;
|
||||||
acceptor->Wait();
|
|
||||||
|
|
||||||
|
acceptor->Run();
|
||||||
|
version_monitor.Run(pool);
|
||||||
|
acceptor->Wait();
|
||||||
|
version_monitor.Shutdown();
|
||||||
service.Shutdown();
|
service.Shutdown();
|
||||||
|
|
||||||
if (unlink_uds) {
|
if (unlink_uds) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue