Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
31 changes: 28 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,35 @@ policy in [docs/versioning.md](docs/versioning.md).

## [Unreleased]

### Breaking

- **The runtime namespace is `opal`, not `smithy`** (#201, ADR-0024; the
first of three surfaces). Smithy is the IDL a service is described in, not
a property of its JSON codec or its HTTP transport, so `smithy::Outcome`,
`smithy::json::Encode` and `smithy::http::BeastServerTransport` are now
`opal::Outcome`, `opal::json::Encode` and
`opal::http::BeastServerTransport` — every `smithy::` scope in the runtime,
in generated code, and in the generated protocol-conformance suites (now
`opal::protocoltests::…`, whose headers moved to
`include/opal/protocoltests/`). Migration: `smithy::` → `opal::` and
`namespace smithy` → `namespace opal` over your tree, with one exclusion.
A C++ namespace you derived from your own model's Smithy namespace is
yours, not the runtime's, and when that model namespace starts with
`smithy.` a blind substitution would rename it too (this repo's rules-test
fixture, `smithy.cpp.ruletest` → `smithy::cpp::ruletest`, is one). Keep
it, and constrain the substitution to the runtime's scopes:
`smithy::http::`, `smithy::json::`, `smithy::cbor::`,
`smithy::eventstream::`, `smithy::server::`, `smithy::testing::`,
`smithy::protocoltests::`, and the top-level runtime types such as
`smithy::Outcome`. Smithy namespaces in `.smithy` files and the
`smithy_cpp_*_library` rules name the model and are unchanged. The
include root (`smithy/http/transport.h`) and the Bazel module
(`@smithy_cpp`) are unchanged here and move in the two PRs that follow.

### Added

- **A dependency-free Prometheus `/metrics` endpoint** (#91, first work
item). `smithy::server::MetricsRegistry` aggregates the existing `Observe`
item). `opal::server::MetricsRegistry` aggregates the existing `Observe`
hooks into the five `http_server_*` families labeled by `service_name`,
`http_method` and `route`, and `MetricsEndpoint` serves them in the
text exposition format, which needs no client library and so costs zero new
Expand Down Expand Up @@ -87,7 +112,7 @@ policy in [docs/versioning.md](docs/versioning.md).
separates a contained crash from a deliberate 500, which report identically
otherwise.

- **A structured access-log formatter** (#203). `smithy::server::FormatAccessLog`
- **A structured access-log formatter** (#203). `opal::server::FormatAccessLog`
turns a `RequestObservation` into one line of JSON — a pure function with
no I/O, no sink, no configuration and no new dependency (`:server` still
takes only `:core` and `:http`; the JSON is hand-rolled like the Prometheus
Expand Down Expand Up @@ -130,7 +155,7 @@ policy in [docs/versioning.md](docs/versioning.md).
now shares the same check); a `float` member cast the parsed double
unchecked on both the body and text-binding paths, so a finite wire value
beyond float range (`1e300`) was undefined behavior per [conv.double] —
the new `smithy::FloatFromDouble` rejects it while NaN/±Infinity still
the new `opal::FloatFromDouble` rejects it while NaN/±Infinity still
pass; and
the jsonRpc2 client truncated `error.code` to `int` *before* its 100–599
range test, classifying 2^32+404 as HTTP 404 (with 5xx codes wrongly
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# The bzlmod module version stays 0.0.0 until the module is published to the
# Bazel Central Registry (deferred, PLAN Phase 6); consumers override the source
# with git_override/local_path_override, which ignores this value. The product
# version consumers actually observe is smithy::Version() / the client
# version consumers actually observe is opal::Version() / the client
# User-Agent ("0.2.0"). See docs/versioning.md.
module(
name = "smithy_cpp",
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ experience assumed. Day 2 (evolving the model) is
Consolidated in one place — if your API depends on any of these, check here before adopting:

- **`@streaming` blobs are not modeled yet.** A streaming blob payload generates as an
ordinary `smithy::Blob`, fully buffered in memory. Event streams, by contrast, are real
ordinary `opal::Blob`, fully buffered in memory. Event streams, by contrast, are real
([ADR-0016](docs/adr/0016-generated-event-streams.md)): a `@streaming` union operation
generates a typed `smithy::eventstream::EventStream` session over WebSocket for all
generates a typed `opal::eventstream::EventStream` session over WebSocket for all
three protocols — `simpleRestJson` and `rpcv2Cbor` ride the event-stream framing codec
([ADR-0014](docs/adr/0014-event-stream-framing-first.md)) and `jsonRpc2` streams
JSON-RPC 2.0 envelopes natively ([ADR-0023](docs/adr/0023-jsonrpc2-event-streams.md)) —
Expand Down
8 changes: 4 additions & 4 deletions bazel/tests/greeter_roundtrip_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ namespace {

class Handler final : public GreeterHandler {
public:
smithy::Outcome<GreetOutput> Greet(const GreetInput& input,
const smithy::server::RequestContext&) override {
opal::Outcome<GreetOutput> Greet(const GreetInput& input,
const opal::server::RequestContext&) override {
return GreetOutput{.greeting = "hello, " + input.name};
}
};

TEST(GreeterMultiModelTest, OverlayBoundServiceRoundTrips) {
GreeterServer server(std::make_shared<Handler>());
auto loopback = std::make_shared<smithy::http::Loopback>();
auto loopback = std::make_shared<opal::http::Loopback>();
ASSERT_TRUE(loopback->Start(server.Handler()).ok());

smithy::ClientConfig config;
opal::ClientConfig config;
config.http_client = loopback;
auto client = GreeterClient::Create(std::move(config));
ASSERT_TRUE(client.ok()) << client.error().message();
Expand Down
36 changes: 18 additions & 18 deletions benchmarks/beast_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@

namespace {

using smithy::testing::kTestCertificatePem;
using smithy::testing::kTestPrivateKeyPem;
using opal::testing::kTestCertificatePem;
using opal::testing::kTestPrivateKeyPem;

// The same input request_benchmark sends, so the numbers are comparable.
example::roundtrip::rest::PutSinkInput MakeInput() {
Expand All @@ -43,26 +43,26 @@ example::roundtrip::rest::PutSinkInput MakeInput() {

class EchoHandler final : public example::roundtrip::rest::RoundTripRestHandler {
public:
smithy::Outcome<example::roundtrip::rest::PutSinkOutput> PutSink(
opal::Outcome<example::roundtrip::rest::PutSinkOutput> PutSink(
const example::roundtrip::rest::PutSinkInput& input,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rest::PutSinkOutput{.sinkId = input.sinkId, .sink = input.sink};
}
smithy::Outcome<example::roundtrip::rest::UploadAttachmentOutput> UploadAttachment(
opal::Outcome<example::roundtrip::rest::UploadAttachmentOutput> UploadAttachment(
const example::roundtrip::rest::UploadAttachmentInput&,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rest::UploadAttachmentOutput{};
}
smithy::Outcome<example::roundtrip::rest::DescribeSinkOutput> DescribeSink(
opal::Outcome<example::roundtrip::rest::DescribeSinkOutput> DescribeSink(
const example::roundtrip::rest::DescribeSinkInput&,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rest::DescribeSinkOutput{};
}
};

example::roundtrip::rest::RoundTripRestClient MakeClient(
std::string endpoint, std::shared_ptr<smithy::http::HttpClient> transport) {
smithy::ClientConfig config;
std::string endpoint, std::shared_ptr<opal::http::HttpClient> transport) {
opal::ClientConfig config;
config.retry.max_attempts = 1;
config.endpoint = std::move(endpoint);
config.http_client = std::move(transport);
Expand All @@ -84,29 +84,29 @@ void RunLoop(benchmark::State& state, example::roundtrip::rest::RoundTripRestCli
// Baseline: the dependency-free socket transport, one connection per request.
void BM_SocketRoundTrip(benchmark::State& state) {
example::roundtrip::rest::RoundTripRestServer server(std::make_shared<EchoHandler>());
smithy::http::SocketHttpServer transport;
opal::http::SocketHttpServer transport;
if (!transport.Start(server.Handler()).ok()) {
state.SkipWithError("socket server failed to start");
return;
}
const std::string origin = "http://127.0.0.1:" + std::to_string(transport.port());
auto client = MakeClient(
origin, std::make_shared<smithy::http::SocketHttpClient>("127.0.0.1", transport.port()));
origin, std::make_shared<opal::http::SocketHttpClient>("127.0.0.1", transport.port()));
RunLoop(state, client);
transport.Stop();
}
BENCHMARK(BM_SocketRoundTrip);

void BM_BeastRoundTrip(benchmark::State& state) {
example::roundtrip::rest::RoundTripRestServer server(std::make_shared<EchoHandler>());
smithy::http::BeastServerTransport transport({.port = 0, .threads = 2});
opal::http::BeastServerTransport transport({.port = 0, .threads = 2});
if (!transport.Start(server.Handler()).ok()) {
state.SkipWithError("beast server failed to start");
return;
}
const std::string origin = "http://127.0.0.1:" + std::to_string(transport.port());
auto client = MakeClient(origin, std::make_shared<smithy::http::BeastHttpClient>(
smithy::http::BeastHttpClient::Options{
auto client = MakeClient(origin, std::make_shared<opal::http::BeastHttpClient>(
opal::http::BeastHttpClient::Options{
.host = "127.0.0.1", .port = transport.port()}));
RunLoop(state, client);
transport.Stop();
Expand All @@ -115,7 +115,7 @@ BENCHMARK(BM_BeastRoundTrip);

void BM_BeastTlsRoundTrip(benchmark::State& state) {
example::roundtrip::rest::RoundTripRestServer server(std::make_shared<EchoHandler>());
smithy::http::BeastServerTransport transport({.port = 0,
opal::http::BeastServerTransport transport({.port = 0,
.threads = 2,
.tls_certificate_chain_pem = kTestCertificatePem,
.tls_private_key_pem = kTestPrivateKeyPem});
Expand All @@ -124,8 +124,8 @@ void BM_BeastTlsRoundTrip(benchmark::State& state) {
return;
}
const std::string origin = "https://127.0.0.1:" + std::to_string(transport.port());
auto client = MakeClient(origin, std::make_shared<smithy::http::BeastHttpClient>(
smithy::http::BeastHttpClient::Options{
auto client = MakeClient(origin, std::make_shared<opal::http::BeastHttpClient>(
opal::http::BeastHttpClient::Options{
.host = "127.0.0.1",
.port = transport.port(),
.tls = true,
Expand Down
28 changes: 14 additions & 14 deletions benchmarks/request_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,41 +43,41 @@ Input MakeInput() {

class RestHandler final : public example::roundtrip::rest::RoundTripRestHandler {
public:
smithy::Outcome<example::roundtrip::rest::PutSinkOutput> PutSink(
opal::Outcome<example::roundtrip::rest::PutSinkOutput> PutSink(
const example::roundtrip::rest::PutSinkInput& input,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rest::PutSinkOutput{.sinkId = input.sinkId, .sink = input.sink};
}
smithy::Outcome<example::roundtrip::rest::UploadAttachmentOutput> UploadAttachment(
opal::Outcome<example::roundtrip::rest::UploadAttachmentOutput> UploadAttachment(
const example::roundtrip::rest::UploadAttachmentInput&,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rest::UploadAttachmentOutput{};
}
smithy::Outcome<example::roundtrip::rest::DescribeSinkOutput> DescribeSink(
opal::Outcome<example::roundtrip::rest::DescribeSinkOutput> DescribeSink(
const example::roundtrip::rest::DescribeSinkInput&,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rest::DescribeSinkOutput{};
}
};

class RpcHandler final : public example::roundtrip::rpc::RoundTripRpcHandler {
public:
smithy::Outcome<example::roundtrip::rpc::PutSinkRpcOutput> PutSinkRpc(
opal::Outcome<example::roundtrip::rpc::PutSinkRpcOutput> PutSinkRpc(
const example::roundtrip::rpc::PutSinkRpcInput& input,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::rpc::PutSinkRpcOutput{.sinkId = input.sinkId, .sink = input.sink};
}
smithy::Outcome<example::roundtrip::rpc::PingOutput> Ping(
const example::roundtrip::rpc::PingInput&, const smithy::server::RequestContext&) override {
opal::Outcome<example::roundtrip::rpc::PingOutput> Ping(
const example::roundtrip::rpc::PingInput&, const opal::server::RequestContext&) override {
return example::roundtrip::rpc::PingOutput{};
}
};

class JsonRpcHandler final : public example::roundtrip::jsonrpc::RoundTripJsonRpcHandler {
public:
smithy::Outcome<example::roundtrip::jsonrpc::PutSinkRpcOutput> PutSinkRpc(
opal::Outcome<example::roundtrip::jsonrpc::PutSinkRpcOutput> PutSinkRpc(
const example::roundtrip::jsonrpc::PutSinkRpcInput& input,
const smithy::server::RequestContext&) override {
const opal::server::RequestContext&) override {
return example::roundtrip::jsonrpc::PutSinkRpcOutput{.sinkId = input.sinkId,
.sink = input.sink};
}
Expand All @@ -87,9 +87,9 @@ template <typename Client, typename Server, typename Handler>
Client MakeLoopbackClient() {
// Handler() owns the router, so the Server object itself may go away.
Server server(std::make_shared<Handler>());
auto loopback = std::make_shared<smithy::http::Loopback>();
auto loopback = std::make_shared<opal::http::Loopback>();
(void)loopback->Start(server.Handler());
smithy::ClientConfig config;
opal::ClientConfig config;
config.retry.max_attempts = 1;
config.http_client = std::move(loopback);
return *Client::Create(std::move(config));
Expand Down
32 changes: 16 additions & 16 deletions benchmarks/serde_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ KitchenSink MakeSink() {
sink.big = 9876543210LL;
sink.ratio = 0.5F;
sink.precise = 3.14159265358979;
sink.blob = smithy::Blob::FromString("0123456789abcdef0123456789abcdef");
sink.blob = opal::Blob::FromString("0123456789abcdef0123456789abcdef");
sink.priority = Priority::Value::kHigh;
sink.weight = Weight::kHeavy;
sink.dateTime = smithy::Timestamp::FromEpochMilliseconds(1515531081000LL);
sink.httpDate = smithy::Timestamp::FromEpochMilliseconds(1515531081000LL);
sink.epoch = smithy::Timestamp::FromEpochMilliseconds(1515531081000LL);
sink.dateTime = opal::Timestamp::FromEpochMilliseconds(1515531081000LL);
sink.httpDate = opal::Timestamp::FromEpochMilliseconds(1515531081000LL);
sink.epoch = opal::Timestamp::FromEpochMilliseconds(1515531081000LL);
sink.names = std::vector<std::string>{"alpha", "beta", "gamma", "delta", "epsilon"};
sink.uniqueNames = std::vector<std::string>{"one", "two", "three"};
sink.sparseNumbers =
Expand All @@ -61,18 +61,18 @@ void BM_SerializeToDocument(benchmark::State& state) {
BENCHMARK(BM_SerializeToDocument);

void BM_DeserializeFromDocument(benchmark::State& state) {
const smithy::Document doc = example::roundtrip::rest::SerializeKitchenSink(MakeSink());
const opal::Document doc = example::roundtrip::rest::SerializeKitchenSink(MakeSink());
for (auto _ : state) {
benchmark::DoNotOptimize(example::roundtrip::rest::DeserializeKitchenSink(doc));
}
}
BENCHMARK(BM_DeserializeFromDocument);

void BM_JsonEncode(benchmark::State& state) {
const smithy::Document doc = example::roundtrip::rest::SerializeKitchenSink(MakeSink());
const opal::Document doc = example::roundtrip::rest::SerializeKitchenSink(MakeSink());
std::size_t bytes = 0;
for (auto _ : state) {
std::string text = smithy::json::Encode(doc);
std::string text = opal::json::Encode(doc);
bytes += text.size();
benchmark::DoNotOptimize(text);
}
Expand All @@ -82,21 +82,21 @@ BENCHMARK(BM_JsonEncode);

void BM_JsonDecode(benchmark::State& state) {
const std::string text =
smithy::json::Encode(example::roundtrip::rest::SerializeKitchenSink(MakeSink()));
opal::json::Encode(example::roundtrip::rest::SerializeKitchenSink(MakeSink()));
std::size_t bytes = 0;
for (auto _ : state) {
benchmark::DoNotOptimize(smithy::json::Decode(text));
benchmark::DoNotOptimize(opal::json::Decode(text));
bytes += text.size();
}
state.SetBytesProcessed(static_cast<std::int64_t>(bytes));
}
BENCHMARK(BM_JsonDecode);

void BM_CborEncode(benchmark::State& state) {
const smithy::Document doc = example::roundtrip::rest::SerializeKitchenSink(MakeSink());
const opal::Document doc = example::roundtrip::rest::SerializeKitchenSink(MakeSink());
std::size_t bytes = 0;
for (auto _ : state) {
smithy::Blob wire = smithy::cbor::Encode(doc);
opal::Blob wire = opal::cbor::Encode(doc);
bytes += wire.size();
benchmark::DoNotOptimize(wire);
}
Expand All @@ -105,11 +105,11 @@ void BM_CborEncode(benchmark::State& state) {
BENCHMARK(BM_CborEncode);

void BM_CborDecode(benchmark::State& state) {
const smithy::Blob wire =
smithy::cbor::Encode(example::roundtrip::rest::SerializeKitchenSink(MakeSink()));
const opal::Blob wire =
opal::cbor::Encode(example::roundtrip::rest::SerializeKitchenSink(MakeSink()));
std::size_t bytes = 0;
for (auto _ : state) {
benchmark::DoNotOptimize(smithy::cbor::Decode(wire));
benchmark::DoNotOptimize(opal::cbor::Decode(wire));
bytes += wire.size();
}
state.SetBytesProcessed(static_cast<std::int64_t>(bytes));
Expand All @@ -120,8 +120,8 @@ void BM_FullPivotRoundTripJson(benchmark::State& state) {
const KitchenSink sink = MakeSink();
for (auto _ : state) {
const std::string text =
smithy::json::Encode(example::roundtrip::rest::SerializeKitchenSink(sink));
auto doc = smithy::json::Decode(text);
opal::json::Encode(example::roundtrip::rest::SerializeKitchenSink(sink));
auto doc = opal::json::Decode(text);
benchmark::DoNotOptimize(example::roundtrip::rest::DeserializeKitchenSink(*doc));
}
}
Expand Down
2 changes: 1 addition & 1 deletion codegen/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ load("@rules_java//java:defs.bzl", "java_binary", "java_library")

package(default_visibility = ["//visibility:public"])

# Read by //tools:release_test, which pins it to smithy::Version().
# Read by //tools:release_test, which pins it to opal::Version().
exports_files(["gradle.properties"])

# The generator, compiled from the same sources the Gradle build uses, so the
Expand Down
Loading
Loading