summaryrefslogtreecommitdiffstats
path: root/yt/cpp/mapreduce/interface/patchable_field.h
blob: 2fe72f6503d1eb3c36b9c9d54e00d0dbddeeff9f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#pragma once

#include "fwd.h"

#include <library/cpp/yson/node/node.h>

namespace NYT {

////////////////////////////////////////////////////////////////////////////////

namespace NDetail {

const TNode::TMapType& GetDynamicConfiguration(const IClientPtr& client, const TString& configProfile);

} // namespace NDetail

////////////////////////////////////////////////////////////////////////////////

// |NYT::TConfig| field supporting per-client overriding with cluster configuration.
// |T| must be one of |TNode| value types.
template <typename T>
class TPatchableField
{
public:
    static constexpr char ConfigProfile[] = "default";

    TPatchableField(TString name, T defaultValue)
        : Name_(std::move(name))
        , Value_(std::move(defaultValue))
    { }

    const T& Get(const IClientPtr& client)
    {
        if (!Patched_) {
            const auto& clusterConfig = NDetail::GetDynamicConfiguration(client, ConfigProfile);
            auto iter = clusterConfig.find(Name_);
            if (!iter.IsEnd()) {
                if (iter->second.IsOfType<T>()) {
                    Value_ = iter->second.As<T>();
                } else {
                    ythrow yexception() << Name_ << " must be " << typeid(T).name();
                }
            }
        }
        return Value_;
    }

    void Set(const T& value)
    {
        Value_ = value;
        Patched_ = true;
    }

private:
    TString Name_;
    T Value_;
    bool Patched_ = false;
};

////////////////////////////////////////////////////////////////////////////////

} // namespace NYT