summaryrefslogtreecommitdiff
path: root/src/buildtool/serve_api/serve_service/target.hpp
blob: ec1e978520ae9237b3cbda342c9c4199dc050f00 (plain)
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_TARGET_HPP
#define INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_TARGET_HPP

#include <filesystem>
#include <memory>
#include <mutex>
#include <string>
#include <vector>

#include <grpcpp/grpcpp.h>

#include "gsl/gsl"
#include "justbuild/just_serve/just_serve.grpc.pb.h"
#include "justbuild/just_serve/just_serve.pb.h"
#include "src/buildtool/common/artifact_digest.hpp"
#include "src/buildtool/common/remote/remote_common.hpp"
#include "src/buildtool/execution_api/common/api_bundle.hpp"
#include "src/buildtool/execution_api/local/context.hpp"
#include "src/buildtool/execution_api/remote/config.hpp"
#include "src/buildtool/execution_api/remote/context.hpp"
#include "src/buildtool/logging/logger.hpp"
#include "src/buildtool/serve_api/remote/config.hpp"
#include "src/buildtool/serve_api/remote/serve_api.hpp"
#include "src/utils/cpp/expected.hpp"

// The target-level cache service.
class TargetService final : public justbuild::just_serve::Target::Service {
  public:
    explicit TargetService(
        gsl::not_null<RemoteServeConfig const*> const& serve_config,
        gsl::not_null<LocalContext const*> const& local_context,
        gsl::not_null<RemoteContext const*> const& remote_context,
        gsl::not_null<ApiBundle const*> const& apis,
        gsl::not_null<std::mutex*> const& lock,
        ServeApi const* serve = nullptr) noexcept
        : serve_config_{*serve_config},
          local_context_{*local_context},
          remote_context_{*remote_context},
          apis_{*apis},
          lock_{lock},
          serve_{serve} {}

    // Given a target-level caching key, returns the computed value. In doing
    // so, it can build on the associated endpoint passing the
    // RemoteExecutionProperties contained in the ServeTargetRequest.
    // The execution backend description, the resulting target cache value,
    // and all other artifacts referenced therein MUST be made available in
    // the CAS of the associated remote-execution endpoint.
    //
    // A failure to analyse or build a known target (i.e., a target for which
    // we have all the needed information available) should NOT be reported as
    // an error. Instead, the failure log should be uploaded as a blob to the
    // CAS of the associated remote-execution endpoint and its digest provided
    // to the client in the response field `log`. In this case, the field
    // `target_value` MUST not be set.
    //
    // If the status has a code different from `OK` or `NOT_FOUND`, the
    // response MUST not be used.
    //
    // Errors:
    // * `NOT_FOUND`: Unknown target or missing needed local information.
    //   This should only be used for non-fatal failures.
    // * `FAILED_PRECONDITION`: Required entries missing in the remote
    //   execution endpoint.
    // * `UNAVAILABLE`: Could not communicate with the remote-execution
    //   endpoint.
    // * `INVALID_ARGUMENT`: The client provided invalid arguments in request.
    // * `INTERNAL`: Internally, something is very broken.
    auto ServeTarget(
        ::grpc::ServerContext* /*context*/,
        const ::justbuild::just_serve::ServeTargetRequest* /*request*/,
        ::justbuild::just_serve::ServeTargetResponse* /*response*/)
        -> ::grpc::Status override;

    // Given the target-level root tree and the name of an export target,
    // returns the list of flexible variables from that target's description.
    //
    // If the status has a code different from `OK`, the response MUST not be
    // used.
    //
    // Errors:
    // * `FAILED_PRECONDITION`: An error occurred in retrieving the
    //   configuration of the requested target, such as missing entries
    //   (target-root, target file, target name), unparsable target file, or
    //   requested target not being of "type" : "export".
    // * `INTERNAL`: Internally, something is very broken.
    auto ServeTargetVariables(
        ::grpc::ServerContext* /*context*/,
        const ::justbuild::just_serve::ServeTargetVariablesRequest* request,
        ::justbuild::just_serve::ServeTargetVariablesResponse* response)
        -> ::grpc::Status override;

    // Given the target-level root tree and the name of an export target,
    // returns the digest of the blob containing the flexible variables field,
    // as well as the documentation fields pertaining tho the target and
    // its configuration variables, as taken from the target's description.
    // This information should be enough for a client to produce locally a
    // full description of said target.
    //
    // The server MUST make the returned blob available in the remote CAS.
    //
    // If the status has a code different from `OK`, the response MUST not be
    // used.
    //
    // Errors:
    // * `FAILED_PRECONDITION`: An error occurred in retrieving the
    //   configuration of the requested target, such as missing entries
    //   (target-root, target file, target name), unparsable target file, or
    //   requested target not being of "type" : "export".
    // * `UNAVAILABLE`: Could not communicate with the remote CAS.
    // * `INTERNAL`: Internally, something is very broken.
    auto ServeTargetDescription(
        ::grpc::ServerContext* /*context*/,
        const ::justbuild::just_serve::ServeTargetDescriptionRequest* request,
        ::justbuild::just_serve::ServeTargetDescriptionResponse* response)
        -> ::grpc::Status override;

  private:
    RemoteServeConfig const& serve_config_;
    LocalContext const& local_context_;
    RemoteContext const& remote_context_;
    ApiBundle const& apis_;
    gsl::not_null<std::mutex*> lock_;
    ServeApi const* const serve_ = nullptr;
    std::shared_ptr<Logger> logger_{std::make_shared<Logger>("target-service")};

    /// \brief Get from remote and parse the endpoint configuration. The method
    /// also ensures the content has the expected format.
    /// \returns The dispatch list stored as JSON object on success or an
    /// unexpected error as grpc::Status.
    [[nodiscard]] auto GetDispatchList(
        ArtifactDigest const& dispatch_digest) noexcept
        -> expected<std::vector<DispatchEndpoint>, ::grpc::Status>;

    /// \brief Handles the processing of the log after a failed analysis or
    /// build. Will populate the response as needed and set the status to be
    /// returned to the client.
    /// \param failure_scope String stating where the failure occurred, to be
    /// included in the local error messaging.
    [[nodiscard]] auto HandleFailureLog(
        std::filesystem::path const& logfile,
        std::string const& failure_scope,
        ::justbuild::just_serve::ServeTargetResponse* response) noexcept
        -> ::grpc::Status;

    /// \brief Create the execution configuration needed to shard the target
    /// cache and dispatch the build to the remote endpoint.
    /// \returns A set up RemoteExecutionConfig or an unexpected error as
    /// grpc::Status.
    [[nodiscard]] auto CreateRemoteExecutionConfig(
        const ::justbuild::just_serve::ServeTargetRequest* request) noexcept
        -> expected<RemoteExecutionConfig, ::grpc::Status>;
};

#endif  // INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_TARGET_HPP