Skip to content

Latest commit

 

History

History
287 lines (252 loc) · 14.6 KB

File metadata and controls

287 lines (252 loc) · 14.6 KB

rgrpc 0.1.2

  • The package installs where gRPC C++ cannot be linked, as a stub whose functions error; the new grpc_available() reports which build is installed, and tests and examples skip on a stub. CRAN's macOS builders have no gRPC, and its libc++ clang builders have only a libstdc++ gRPC, which linked into a shared object that then failed to load. configure now links a test program with R's own C++ compiler instead of trusting pkg-config alone. RGRPC_REQUIRE_GRPC=true turns the stub fallback into an install error; CI sets it on the legs that have gRPC and adds a leg without it.
  • The .Call routine table moved to src/routines.h, shared by the real build and the stub.
  • gRPC is initialized once, when the DLL loads, and shut down at unload or R exit, instead of coming up and down with every client and server. Each start ran abseil's debug deadlock bookkeeping, whose frame-pointer stack walk read uninitialized stack through the package's frames on builds without frame pointers: the valgrind reports on CRAN's Fedora machine. Fork behavior is unchanged (tools/fork-probe.sh).
  • configure compiles its gRPC link test with R's PIC flags, so a -pie in LDFLAGS no longer fails it on hardened toolchains.
  • configure checks for pkg-config with pkg-config --version rather than command -v, which R-devel's check flags as a possible bashism.
  • On macOS the package links CoreFoundation, which a static abseil (as in CRAN's macOS recipes) needs but does not list in its pkg-config files.
  • SystemRequirements names the Fedora (grpc-cpp, grpc-devel, protobuf-devel) and Homebrew packages as well as the Debian ones.
  • The TLS tests set certificate extensions explicitly, so they pass with OpenSSL 1.1, OpenSSL 3, and LibreSSL, and stop cleanly if the certificates cannot be generated.
  • configure drops warning options from pkg-config's flags and passes the include directories as -isystem. abseil's .pc files carry its own -Wno-... options, which R CMD check reported as non-portable flags, and gRPC 1.83's headers raise deprecation warnings against newer abseil releases (Homebrew), which it reported as the package's.
  • CI installs checkbashisms on macOS, targets the runner's macOS when linking Homebrew's gRPC, and fails on check WARNINGs.

rgrpc 0.1.1

  • First CRAN release, resubmitted after the review of 0.1.0. DESCRIPTION links the gRPC project and its C++ API; every exported function documents its return value, including the seven called for their side effects; and the examples run instead of sitting in \dontrun{}: each one drives a client and a server in the same process over the loopback interface. grpc_tls() keeps a \dontrun{} example because it needs certificate files.

rgrpc 0.1.0

  • Renamed from grpc to rgrpc before the first release: the bare name is a search token owned by the upstream project, and a unique name keeps this package's docs and issues findable. Exported functions keep their grpc_* names.
  • First CRAN submission (returned for documentation fixes; see 0.1.1): an asynchronous gRPC client and server runtime on the generic C++ API, with unary and streaming calls, TLS/mTLS, deadlines, keepalive, cancellation, and event-loop integration via grpc_fd(). Runs on Linux, Windows (Rtools >= 4.3), and macOS. The 0.0.1.x entries below record the development history.

rgrpc 0.0.1.14

  • The package builds on Windows and macOS. The completion wake-up was the one platform-bound piece of the runtime: eventfd is Linux-only, and src/wake.h replaces it with the same contract everywhere -- a self-pipe on Unix, a loopback socket pair on Windows, readable exactly while events are queued. Windows links the gRPC that Rtools >= 4.3 bundles, through a static Makevars.win, and OS_type: unix left DESCRIPTION. CI gains a macOS leg building against Homebrew's gRPC.

rgrpc 0.0.1.13

  • Depends dropped from R (>= 4.4.0) to R (>= 4.3.0), the version noble ships. (This heading was added retroactively; the bump rode with the change in #23 without a NEWS entry.)

rgrpc 0.0.1.12

  • grpc_await() now works on a server "grpc_request" too, closing the asymmetry 0.0.1.11 left behind: the docs said "one queue serves the whole client or server" while the remedy shipped for the client only, so a server driving concurrent streaming calls still hand-rolled the id dispatch that had already gone wrong five times downstream. A handler can drain one client-streaming call with grpc_await(req, timeout_ms) and see nothing belonging to any other.
  • grpc_await() became an S3 generic to accommodate that third class. Call sites are unaffected: the signature is unchanged and the existing "grpc_call" and "grpc_stream" behaviour is identical.
  • On a server request the awaited events are the ones that follow the request itself ("stream_msg", "client_done", "stream_writable", "cancelled"), since the request arrives from grpc_poll() in the first place. A server call has no terminal event of its own -- it ends when the handler ends it -- so "client_done" is what a client-streaming handler loops to.

rgrpc 0.0.1.11

  • New grpc_await(x, timeout_ms): waits for events belonging to one call or stream. Other calls' events are stepped over and left queued in arrival order, and the wait ends only when a matching event arrives. This is the demultiplexing every other gRPC binding does for you -- Python hands back a per-call future or response iterator and never exposes a completion queue -- and its absence is what made the attribution mistakes in 0.0.1.10 possible in the first place. Use it for sequential code; use grpc_poll() and dispatch on id when calls really are concurrent, since awaiting one call means not looking at the others.
  • The filter lives in C over the existing ready deque rather than in an R-side buffer, so there is no second queue to keep in sync and a filtered read cannot lose or reorder another call's events. The wait is filter-aware: it cannot lean on the eventfd, because another call's queued events keep the descriptor readable and the wait would spin instead of blocking.
  • An expired grpc_await() leaves the call exactly as it was: await it again to keep waiting. That resumability is what keeps a required timeout_ms from being the empty-batch trap in new clothing, so it is now stated rather than implied, along with which clock is which (deadline_ms bounds the RPC, timeout_ms bounds one wait). Examples check the batch before indexing it: on a slow peer grpc_await(call, timeout_ms = 1000)[[1]] raises subscript out of bounds, which reads like a caller bug rather than the timeout it is.
  • The documentation stopped teaching the bug. The README's round-trip and typed-call examples, and inst/examples/cri-list-pods.R, all indexed a poll batch as evs[[1]] or hand-rolled a drain() helper that returned the first event of whatever arrived. Correct only while nothing else is in flight, which is exactly how a caller infers the wrong model.

rgrpc 0.0.1.10

  • Fixed spurious wake-ups from grpc_poll() (#12). The eventfd carries one signal per event, but the counter was drained outside the mutex guarding the ready deque, so every signal posted between the drain and the batch below stayed counted even though the batch took those events. The leftover count was then spent as instant, empty polls: a caller that reads "no events" as "this call never started" abandons a live stream, which showed up as sequential server-streaming calls on a shared client failing 1-7 times in 30. The drain and a re-arm now happen under that mutex, so the descriptor is readable exactly while events are queued. Affects clients and servers alike, and grpc_fd() integrations most of all, since a partial batch used to leave the descriptor unreadable with events still pending.
  • Documented what an empty grpc_poll() result means: the wait expired, not that the call is over.
  • Documented event attribution: one queue serves the whole client, so a batch can mix events from every call in flight, in completion order, and callers must dispatch on id. Taking events[[1]] as the answer to a unary call and accumulating every "stream_msg" into one stream's payload are the same assumption -- one queue per call -- and it does not hold. Abandoning a stream unread does not stop it, and its queued messages go on surfacing alongside later calls; grpc_cancel() bounds how many more are produced but cannot recall events already queued. Verified against the runtime rather than assumed: over 40 rounds of a deliberately abandoned stream followed by a second stream on the same client, no event's id ever disagreed with its payload, while an accumulator that ignored id got the wrong byte count 36 times out of 40.

rgrpc 0.0.1.9

  • Fixed a use-after-free race found by the first genuinely instrumented ThreadSanitizer run: grpc_r_call_start() and grpc_r_stream_start() read the call id after releasing the mutex, and a fast completion can free the call state on the drain thread in that window. The id is now captured under the lock.
  • tools/sanitize.sh is fail-closed about its own preconditions, after three stacked silent failures let earlier sanitizer passes run the plain build: libraries are injected via R_LIBS and asserted with find.package() (littler's -L silently does not prepend), sanitizer flags go through CXX17FLAGS and instrumentation is proven via __asan/__tsan symbols in the built .so, installs use --preclean, an exit trap removes flagged objects even on failure, non-data-race TSan warnings are fatal, and the report classifier self-tests against synthetic logs at every run.

rgrpc 0.0.1.8

  • Keepalive: keepalive_ms/keepalive_timeout_ms on grpc_client() and grpc_server(), plus min_ping_interval_ms (server tolerance for client pings; gRPC's default is 5 minutes and kills faster clients). Enabling keepalive also lifts gRPC's ping policing so pings flow on quiet connections.
  • Abortive close: grpc_finish(drain = FALSE) discards queued stream writes and prioritizes the terminal status (fencing); grpc_cancel() now also works on server requests as the hard escalation past a peer that has stopped reading.

rgrpc 0.0.1.7

  • Fixed a completion-queue shutdown race that aborted the process when closing a client (or server) with stream operations in flight: the drain thread could post a follow-on op after cq.Shutdown(). A shutting flag now suppresses all drain-thread op posts during close, on both client and server.
  • Forced-error cleanup tests: post-close operations error cleanly, finalizers with work in flight, create/destroy churn.
  • Verified under valgrind (0 errors, 0 definite/indirect leaks; possibly-lost noise from gRPC/absl thread-locals and R remains), AddressSanitizer (clean), and ThreadSanitizer (all reports trace to the uninstrumented system libgrpc boundary; none in package code).
  • Reference node image under docker/: two-stage build on rocker/r2u:noble, runtime carries only libgrpc++1.51t64 and r-cran-rprotobuf; built and smoke-tested. The base image release must match the build host's — the binary is tied to the distro ABI.
  • configure and SystemRequirements now name libprotobuf-dev alongside libgrpc++-dev (not pulled automatically under --no-install-recommends).

rgrpc 0.0.1.6

  • Operational surface: grpc_tls() builds PEM credentials for both sides (TLS server, CA-pinned client, mTLS with require_client_cert, target_name_override for testing); server request events carry the transport peer and, under mTLS, the verified peer_identity; grpc_state() observes channel connectivity; GRPC_TRACE/GRPC_VERBOSITY documented.
  • Health checking (grpc.health.v1) and server reflection (grpc.reflection.v1) protos vendored and proven through the generic path — unary Check and bidi ServerReflectionInfo — with no special machinery.

rgrpc 0.0.1.5

  • Streaming: grpc_stream() opens client-, server-, and bidirectional streams (typed or raw); grpc_send() (bounded write queue with stream_writable backpressure events), grpc_writes_done(), automatic bounded inbound buffering with HTTP/2 backpressure, and a terminal stream_status event. Server side: grpc_read() pulls inbound stream messages, grpc_send() queues outbound ones, grpc_finish() ends the stream after writes drain. grpc_cancel() is now a generic over calls and streams; client events carry kind.
  • Live CRI streaming smoke: subscribe, hold, and cancel GetContainerEvents against containerd.

rgrpc 0.0.1.4

  • Real-world proof: CRI client against live containerd (v2.2.3) over a unix-domain socket — Version, ListPodSandbox, ListImages, all through the typed layer. CRI v1 schema vendored as a self-contained import root under inst/proto/cri; live tests gate on socket access (GRPC_R_CRI_SOCKET); inst/examples/cri-list-pods.R for humans.
  • PLAN.md: Viento experiment reframed as control-plane candidacy.

rgrpc 0.0.1.3

  • RProtoBuf integration: grpc_service() / grpc_method() resolve services and methods from the runtime descriptor pool (via the FileDescriptorProto, sidestepping rprotobuf#116); grpc_call() accepts a grpc_method plus a Message, validates the request type, and auto-decodes OK responses as response_message; grpc_reply() accepts a Message; grpc_decode() decodes payload bytes. RProtoBuf remains a Suggests.

rgrpc 0.0.1.2

  • Generic asynchronous server on AsyncGenericService: grpc_server() accepts any method dynamically; grpc_reply() answers with a payload or a typed status plus trailing metadata. Bounded accept window and max_active apply backpressure.
  • grpc_poll(), grpc_fd(), grpc_pending(), and grpc_close() are now S3 generics over clients and servers. Peer cancellation and deadline expiry surface as "cancelled" events; late replies are refused rather than crashing.
  • Full in-process round trips (TCP and unix-domain sockets) covered in tests.

rgrpc 0.0.1.1

  • Generic asynchronous unary client on GenericStub: grpc_client(), grpc_call(), grpc_poll(), grpc_cancel(), grpc_pending(), grpc_close(), with deadlines, metadata, and typed status codes.
  • Event-loop wakeup via eventfd, exposed through grpc_fd() for later::later_fd()-style integration; polling is the fallback, not the primitive.

rgrpc 0.0.1

  • Initial skeleton: system-linked build against the distro gRPC C++ library via pkg-config, spike shim proving safe create/destroy of channels, completion queues, and generic servers.