Skip to content

Commit b50fb7c

Browse files
achamayouCopilot
andcommitted
Harden Rust bridge integration
Preserve compaction retry semantics, reject unsupported HTTP status codes, and keep the CI test bucket inventory in sync. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent ae04da5 commit b50fb7c

4 files changed

Lines changed: 88 additions & 23 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the Apache 2.0 License.
3+
#pragma once
4+
5+
#include <string>
6+
#include <utility>
7+
8+
namespace ccf::kv
9+
{
10+
class CompactedVersionConflict
11+
{
12+
private:
13+
std::string msg;
14+
15+
public:
16+
CompactedVersionConflict(std::string s) : msg(std::move(s)) {}
17+
18+
[[nodiscard]] char const* what() const
19+
{
20+
return msg.c_str();
21+
}
22+
};
23+
}

src/kv/compacted_version_conflict.h

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,4 @@
22
// Licensed under the Apache 2.0 License.
33
#pragma once
44

5-
#include <string>
6-
7-
namespace ccf::kv
8-
{
9-
class CompactedVersionConflict
10-
{
11-
private:
12-
std::string msg;
13-
14-
public:
15-
CompactedVersionConflict(std::string s) : msg(std::move(s)) {}
16-
17-
[[nodiscard]] char const* what() const
18-
{
19-
return msg.c_str();
20-
}
21-
};
22-
}
5+
#include "ccf/kv/compacted_version_conflict.h"

src/rust/app_bridge.cpp

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "ccf/app_interface.h"
55
#include "ccf/common_auth_policies.h"
66
#include "ccf/http_status.h"
7+
#include "ccf/kv/compacted_version_conflict.h"
78
#include "ccf/kv/map.h"
89
#include "ccf/odata_error.h"
910
#include "ccf/rust_ffi.h"
1011

1112
#include <memory>
13+
#include <optional>
1214
#include <string>
1315
#include <unordered_map>
1416
#include <utility>
@@ -92,6 +94,20 @@ namespace
9294
return value.data != nullptr || value.len == 0;
9395
}
9496

97+
bool is_known_http_status(uint16_t status)
98+
{
99+
switch (status)
100+
{
101+
#define XX(code, name, string) \
102+
case code: \
103+
return true;
104+
HTTP_STATUS_MAP(XX)
105+
#undef XX
106+
default:
107+
return false;
108+
}
109+
}
110+
95111
std::string to_string(const ccf_rust_slice& value)
96112
{
97113
if (value.len == 0)
@@ -156,6 +172,8 @@ struct ccf_rust_endpoint_context
156172
std::unordered_map<std::string, RawMap::ReadOnlyHandle*> read_handles;
157173
std::unordered_map<std::string, RawMap::Handle*> write_handles;
158174
RawMap::Handle::ValueType scratch;
175+
std::optional<ccf::kv::CompactedVersionConflict> compacted_version_conflict =
176+
std::nullopt;
159177

160178
RawMap::ReadOnlyHandle* read_handle(const std::string& map_name)
161179
{
@@ -188,6 +206,14 @@ struct ccf_rust_endpoint_context
188206
read_handles[map_name] = handle;
189207
return handle;
190208
}
209+
210+
void rethrow_compacted_version_conflict()
211+
{
212+
if (compacted_version_conflict.has_value())
213+
{
214+
throw std::move(compacted_version_conflict.value());
215+
}
216+
}
191217
};
192218

193219
namespace
@@ -235,14 +261,20 @@ namespace
235261
ctx.rpc_ctx, &ctx.tx, nullptr, {}, {}, {}};
236262
try
237263
{
238-
if (state->callback(state->user_data, &rust_ctx) != CCF_RUST_OK)
264+
const auto result = state->callback(state->user_data, &rust_ctx);
265+
rust_ctx.rethrow_compacted_version_conflict();
266+
if (result != CCF_RUST_OK)
239267
{
240268
ctx.rpc_ctx->set_error(
241269
HTTP_STATUS_INTERNAL_SERVER_ERROR,
242270
ccf::errors::InternalError,
243271
"Rust endpoint execution failed");
244272
}
245273
}
274+
catch (const ccf::kv::CompactedVersionConflict&)
275+
{
276+
throw;
277+
}
246278
catch (const std::exception& e)
247279
{
248280
ctx.rpc_ctx->set_error(
@@ -271,14 +303,20 @@ namespace
271303
ctx.rpc_ctx, &ctx.tx, &ctx.tx, {}, {}, {}};
272304
try
273305
{
274-
if (state->callback(state->user_data, &rust_ctx) != CCF_RUST_OK)
306+
const auto result = state->callback(state->user_data, &rust_ctx);
307+
rust_ctx.rethrow_compacted_version_conflict();
308+
if (result != CCF_RUST_OK)
275309
{
276310
ctx.rpc_ctx->set_error(
277311
HTTP_STATUS_INTERNAL_SERVER_ERROR,
278312
ccf::errors::InternalError,
279313
"Rust endpoint execution failed");
280314
}
281315
}
316+
catch (const ccf::kv::CompactedVersionConflict&)
317+
{
318+
throw;
319+
}
282320
catch (const std::exception& e)
283321
{
284322
ctx.rpc_ctx->set_error(
@@ -436,7 +474,7 @@ extern "C"
436474

437475
int ccf_rust_response_status(ccf_rust_endpoint_context* ctx, uint16_t status)
438476
{
439-
if (ctx == nullptr || status < 100 || status > 599)
477+
if (ctx == nullptr || !is_known_http_status(status))
440478
{
441479
return CCF_RUST_INVALID_ARGUMENT;
442480
}
@@ -496,8 +534,8 @@ extern "C"
496534
ccf_rust_slice message)
497535
{
498536
if (
499-
ctx == nullptr || status < 400 || status > 599 || !is_valid_utf8(code) ||
500-
code.len == 0 || !is_valid_utf8(message))
537+
ctx == nullptr || status < 400 || !is_known_http_status(status) ||
538+
!is_valid_utf8(code) || code.len == 0 || !is_valid_utf8(message))
501539
{
502540
return CCF_RUST_INVALID_ARGUMENT;
503541
}
@@ -539,6 +577,11 @@ extern "C"
539577
set_slice(value, ctx->scratch);
540578
return CCF_RUST_OK;
541579
}
580+
catch (const ccf::kv::CompactedVersionConflict& e)
581+
{
582+
ctx->compacted_version_conflict = e;
583+
return CCF_RUST_INTERNAL_ERROR;
584+
}
542585
catch (...)
543586
{
544587
return CCF_RUST_INTERNAL_ERROR;
@@ -563,6 +606,11 @@ extern "C"
563606
ctx->read_handle(to_string(map_name))->has(to_bytes(key)) ? 1 : 0;
564607
return CCF_RUST_OK;
565608
}
609+
catch (const ccf::kv::CompactedVersionConflict& e)
610+
{
611+
ctx->compacted_version_conflict = e;
612+
return CCF_RUST_INTERNAL_ERROR;
613+
}
566614
catch (...)
567615
{
568616
return CCF_RUST_INTERNAL_ERROR;
@@ -591,6 +639,11 @@ extern "C"
591639
handle->put(to_bytes(key), to_bytes(value));
592640
return CCF_RUST_OK;
593641
}
642+
catch (const ccf::kv::CompactedVersionConflict& e)
643+
{
644+
ctx->compacted_version_conflict = e;
645+
return CCF_RUST_INTERNAL_ERROR;
646+
}
594647
catch (...)
595648
{
596649
return CCF_RUST_INTERNAL_ERROR;
@@ -616,6 +669,11 @@ extern "C"
616669
handle->remove(to_bytes(key));
617670
return CCF_RUST_OK;
618671
}
672+
catch (const ccf::kv::CompactedVersionConflict& e)
673+
{
674+
ctx->compacted_version_conflict = e;
675+
return CCF_RUST_INTERNAL_ERROR;
676+
}
619677
catch (...)
620678
{
621679
return CCF_RUST_INTERNAL_ERROR;

tests/ci-buckets.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ bucket_c:
2020
governance_test
2121
code_update_test
2222
e2e_logging
23+
basic_rust
2324
programmability_and_jwt
2425
e2e_limits
2526
e2e_redirects

0 commit comments

Comments
 (0)