Skip to content

Commit 7095c30

Browse files
Merge branch 'master' into jlarabie/hangman
2 parents e7dd14c + 5c04860 commit 7095c30

145 files changed

Lines changed: 9783 additions & 737 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -887,13 +887,26 @@ jobs:
887887
&& (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }}
888888
permissions:
889889
contents: read
890+
pull-requests: read
890891
runs-on: ubuntu-latest
891892
env:
892893
TARGET_OWNER: clockworklabs
893894
TARGET_REPO: SpacetimeDBPrivate
894895
steps:
896+
# Skip the private dispatch entirely when only `docs/` is touched. The job
897+
# itself still completes successfully so required-status-check gating is
898+
# satisfied without spending private-runner time on a docs-only change.
899+
- name: Detect non-docs changes
900+
id: filter
901+
uses: dorny/paths-filter@v3
902+
with:
903+
filters: |
904+
non_docs:
905+
- '!docs/**'
906+
895907
- id: dispatch
896908
name: Trigger tests
909+
if: steps.filter.outputs.non_docs == 'true'
897910
uses: actions/github-script@v7
898911
with:
899912
github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }}
@@ -957,6 +970,7 @@ jobs:
957970
core.setOutput('run_url', runUrl);
958971

959972
- name: Wait for Internal Tests to complete
973+
if: steps.filter.outputs.non_docs == 'true'
960974
uses: actions/github-script@v7
961975
with:
962976
github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }}
@@ -994,7 +1008,7 @@ jobs:
9941008
}
9951009

9961010
- name: Cancel invoked run if workflow cancelled
997-
if: ${{ cancelled() }}
1011+
if: ${{ cancelled() && steps.dispatch.outputs.run_id }}
9981012
uses: actions/github-script@v7
9991013
with:
10001014
github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }}

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bindings-cpp/CMakeLists.txt

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ target_sources(spacetimedb_cpp_library PRIVATE ${LIBRARY_SOURCES})
3030

3131
# Require C++20 for consumers of this library without forcing global flags
3232
target_compile_features(spacetimedb_cpp_library PUBLIC cxx_std_20)
33+
target_compile_definitions(spacetimedb_cpp_library PRIVATE SPACETIMEDB_UNSTABLE_FEATURES)
3334

3435
# Set include directories
3536
target_include_directories(spacetimedb_cpp_library
@@ -60,46 +61,5 @@ if(PROJECT_IS_TOP_LEVEL)
6061
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
6162
endif()
6263

63-
# ---- Tests ----
64-
# Default: ON only when building this project directly; OFF when used via FetchContent/add_subdirectory
65-
if(CMAKE_VERSION VERSION_LESS 3.21)
66-
# Fallback heuristic for older CMake
67-
set(_is_top_level FALSE)
68-
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
69-
set(_is_top_level TRUE)
70-
endif()
71-
else()
72-
set(_is_top_level ${PROJECT_IS_TOP_LEVEL})
73-
endif()
74-
75-
option(BUILD_TESTS "Build the test suite" ${_is_top_level})
76-
77-
if(BUILD_TESTS AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
78-
enable_testing()
79-
80-
# Add test executable
81-
add_executable(test_bsatn tests/main.cpp tests/module_library_unit_tests.cpp)
82-
83-
# Link against the module library
84-
target_link_libraries(test_bsatn PRIVATE spacetimedb_cpp_library)
85-
86-
# Set C++20 standard for tests
87-
target_compile_features(test_bsatn PRIVATE cxx_std_20)
88-
89-
# Add test to CTest
90-
add_test(NAME bsatn_tests COMMAND test_bsatn)
91-
92-
# Add verbose test variant
93-
add_test(NAME bsatn_tests_verbose COMMAND test_bsatn -v)
94-
95-
# Set test properties
96-
set_tests_properties(bsatn_tests PROPERTIES
97-
TIMEOUT 30
98-
LABELS "unit"
99-
)
100-
101-
set_tests_properties(bsatn_tests_verbose PROPERTIES
102-
TIMEOUT 30
103-
LABELS "unit;verbose"
104-
)
105-
endif()
64+
# Unit/compile/smoke test harnesses live under `tests/` as standalone runners
65+
# rather than being built through the top-level library CMake target.

crates/bindings-cpp/include/spacetimedb.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@
126126

127127
// Procedure context and macros
128128
#include "spacetimedb/procedure_macros.h"
129+
#ifdef SPACETIMEDB_UNSTABLE_FEATURES
130+
#include "spacetimedb/handler_context.h"
131+
#include "spacetimedb/router.h"
132+
#include "spacetimedb/http_handler_macros.h"
133+
#endif
129134

130135
// =============================================================================
131136
// VIEW SYSTEM

crates/bindings-cpp/include/spacetimedb/abi/abi.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,37 @@ int16_t __call_reducer__(
216216
BytesSource args,
217217
BytesSink error);
218218

219+
STDB_EXPORT(__call_view__)
220+
int16_t __call_view__(
221+
uint32_t id,
222+
uint64_t sender_0, uint64_t sender_1, uint64_t sender_2, uint64_t sender_3,
223+
BytesSource args,
224+
BytesSink result);
225+
226+
STDB_EXPORT(__call_view_anon__)
227+
int16_t __call_view_anon__(
228+
uint32_t id,
229+
BytesSource args,
230+
BytesSink result);
231+
232+
STDB_EXPORT(__call_procedure__)
233+
int16_t __call_procedure__(
234+
uint32_t id,
235+
uint64_t sender_0, uint64_t sender_1, uint64_t sender_2, uint64_t sender_3,
236+
uint64_t conn_id_0, uint64_t conn_id_1,
237+
uint64_t timestamp_microseconds,
238+
BytesSource args_source,
239+
BytesSink result_sink);
240+
241+
STDB_EXPORT(__call_http_handler__)
242+
int16_t __call_http_handler__(
243+
uint32_t id,
244+
uint64_t timestamp_microseconds,
245+
BytesSource request_source,
246+
BytesSource request_body_source,
247+
BytesSink response_sink,
248+
BytesSink response_body_sink);
249+
219250
// ========================================================================
220251
// WASI SHIMS
221252
// ========================================================================
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#ifndef SPACETIMEDB_HANDLER_CONTEXT_H
2+
#define SPACETIMEDB_HANDLER_CONTEXT_H
3+
4+
#ifndef SPACETIMEDB_UNSTABLE_FEATURES
5+
#error "spacetimedb/handler_context.h requires SPACETIMEDB_UNSTABLE_FEATURES to be enabled"
6+
#endif
7+
8+
#include <spacetimedb/abi/FFI.h>
9+
#include <spacetimedb/bsatn/timestamp.h>
10+
#include <spacetimedb/bsatn/uuid.h>
11+
#include <spacetimedb/http.h>
12+
#include <spacetimedb/internal/tx_execution.h>
13+
#include <spacetimedb/random.h>
14+
#include <spacetimedb/tx_context.h>
15+
#include <array>
16+
#include <cstdint>
17+
#include <functional>
18+
#include <memory>
19+
#include <optional>
20+
#include <type_traits>
21+
22+
namespace SpacetimeDB {
23+
24+
struct HandlerContext {
25+
Timestamp timestamp;
26+
HttpClient http;
27+
28+
private:
29+
mutable std::shared_ptr<StdbRng> rng_instance;
30+
mutable uint32_t counter_uuid_ = 0;
31+
32+
public:
33+
HandlerContext() = default;
34+
explicit HandlerContext(Timestamp t) : timestamp(t) {}
35+
36+
Identity identity() const {
37+
std::array<uint8_t, 32> id_bytes;
38+
::identity(id_bytes.data());
39+
return Identity(id_bytes);
40+
}
41+
42+
StdbRng& rng() const {
43+
if (!rng_instance) {
44+
rng_instance = std::make_shared<StdbRng>(timestamp);
45+
}
46+
return *rng_instance;
47+
}
48+
49+
Uuid new_uuid_v4() const {
50+
std::array<uint8_t, 16> random_bytes;
51+
rng().fill_bytes(random_bytes.data(), random_bytes.size());
52+
return Uuid::from_random_bytes_v4(random_bytes);
53+
}
54+
55+
Uuid new_uuid_v7() const {
56+
std::array<uint8_t, 4> random_bytes;
57+
rng().fill_bytes(random_bytes.data(), random_bytes.size());
58+
return Uuid::from_counter_v7(counter_uuid_, timestamp, random_bytes);
59+
}
60+
61+
#ifdef SPACETIMEDB_UNSTABLE_FEATURES
62+
template<typename Func>
63+
auto with_tx(Func&& body) -> decltype(body(std::declval<TxContext&>())) {
64+
auto make_reducer_ctx = [](Timestamp tx_timestamp) {
65+
return ReducerContext(
66+
Identity{},
67+
std::nullopt,
68+
tx_timestamp,
69+
AuthCtx::internal()
70+
);
71+
};
72+
return Internal::with_tx(make_reducer_ctx, body);
73+
}
74+
75+
template<typename Func>
76+
auto try_with_tx(Func&& body) -> decltype(body(std::declval<TxContext&>())) {
77+
auto make_reducer_ctx = [](Timestamp tx_timestamp) {
78+
return ReducerContext(
79+
Identity{},
80+
std::nullopt,
81+
tx_timestamp,
82+
AuthCtx::internal()
83+
);
84+
};
85+
return Internal::try_with_tx(make_reducer_ctx, body);
86+
}
87+
#endif
88+
};
89+
90+
} // namespace SpacetimeDB
91+
92+
#endif // SPACETIMEDB_HANDLER_CONTEXT_H

crates/bindings-cpp/include/spacetimedb/http.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
#pragma once
55

6+
#ifndef SPACETIMEDB_UNSTABLE_FEATURES
7+
#error "spacetimedb/http.h requires SPACETIMEDB_UNSTABLE_FEATURES to be enabled"
8+
#endif
9+
610
#include <string>
711
#include <vector>
812
#include <optional>
@@ -312,8 +316,10 @@ class HttpClient {
312316

313317
} // namespace SpacetimeDB
314318

315-
// Include implementation after class definition to avoid circular dependencies
316-
#ifdef SPACETIMEDB_UNSTABLE_FEATURES
319+
// Include implementation dependencies after class definition to avoid circular dependencies
320+
#if defined(SPACETIMEDB_UNSTABLE_FEATURES) && !defined(SPACETIMEDB_HTTP_CONVERT_H)
321+
#include "spacetimedb/logger.h"
322+
#include "spacetimedb/http_convert.h"
317323
#include "spacetimedb/http_client_impl.h"
318324
#endif
319325

crates/bindings-cpp/include/spacetimedb/http_client_impl.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "spacetimedb/http_convert.h"
88
#include "spacetimedb/abi/abi.h"
99
#include "spacetimedb/bsatn/bsatn.h"
10-
#include "spacetimedb/internal/Module.h"
10+
#include "spacetimedb/internal/runtime_registration.h"
1111

1212
namespace SpacetimeDB {
1313

@@ -23,9 +23,9 @@ inline Outcome<HttpResponse> HttpClient::SendImpl(const HttpRequest& request) {
2323
// Prepare body bytes
2424
const std::vector<uint8_t>& body_bytes = request.body.bytes;
2525

26-
// Call host function
27-
// Note: For empty body, we need to pass a valid pointer, not null
28-
const uint8_t* body_ptr = body_bytes.empty() ? reinterpret_cast<const uint8_t*>("") : body_bytes.data();
26+
// The host ABI requires a non-null, in-bounds body pointer even when body_len == 0.
27+
static const uint8_t empty_sentinel = 0;
28+
const uint8_t* body_ptr = body_bytes.empty() ? &empty_sentinel : body_bytes.data();
2929

3030
BytesSource out[2] = {BytesSource{0}, BytesSource{0}};
3131
Status status = procedure_http_request(
@@ -40,15 +40,11 @@ inline Outcome<HttpResponse> HttpClient::SendImpl(const HttpRequest& request) {
4040
if (status.inner == 21) {
4141
// Read error message from out[0]
4242
std::vector<uint8_t> error_bytes = Internal::ConsumeBytes(out[0]);
43-
44-
LOG_INFO("HTTP: Error bytes: " + std::to_string(error_bytes.size()));
45-
43+
4644
// Decode BSATN string
4745
bsatn::Reader reader(error_bytes.data(), error_bytes.size());
4846
std::string error_message = bsatn::deserialize<std::string>(reader);
4947

50-
LOG_INFO("HTTP: Error message: " + error_message);
51-
5248
return Err<HttpResponse>(std::move(error_message));
5349
}
5450

@@ -57,7 +53,6 @@ inline Outcome<HttpResponse> HttpClient::SendImpl(const HttpRequest& request) {
5753
return Err<HttpResponse>("HTTP requests are blocked inside transactions. Call HTTP before with_tx() or try_with_tx().");
5854
}
5955

60-
LOG_INFO("HTTP: Unknown error code: " + std::to_string(status.inner));
6156
return Err<HttpResponse>("HTTP request failed with status code: " + std::to_string(status.inner));
6257
}
6358

crates/bindings-cpp/include/spacetimedb/http_convert.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,12 @@ inline HttpRequest from_wire(const wire::HttpRequest& request) {
237237
return result;
238238
}
239239

240+
inline HttpRequest from_wire(const wire::HttpRequest& request, std::vector<uint8_t> body) {
241+
HttpRequest result = from_wire(request);
242+
result.body.bytes = std::move(body);
243+
return result;
244+
}
245+
240246
// ==================== HttpResponse Conversions ====================
241247

242248
/**
@@ -268,7 +274,16 @@ inline HttpResponse from_wire(const wire::HttpResponse& response) {
268274
return result;
269275
}
270276

277+
inline std::pair<wire::HttpResponse, std::vector<uint8_t>> to_wire_split(const HttpResponse& response) {
278+
return {to_wire(response), response.body.bytes};
279+
}
280+
271281
} // namespace convert
272282
} // namespace SpacetimeDB
273283

284+
#ifdef SPACETIMEDB_UNSTABLE_FEATURES
285+
#include "spacetimedb/logger.h"
286+
#include "spacetimedb/http_client_impl.h"
287+
#endif
288+
274289
#endif // SPACETIMEDB_HTTP_CONVERT_H

0 commit comments

Comments
 (0)