Runnable gRPC samples for the thesis stack. Each sample lives under src/<name>/
and uses whichever proto fits (see protos/). Add your own proto when a case needs one.
Commands run inside the PHP container:
make run CMD='php <path>'The server listens on 0.0.0.0:50051 and the client connects to 127.0.0.1:50051
by default, so nothing needs wiring. Start the server in one shell, the client in
another.
Serves the gRPC Server Reflection protocol, so tools like grpcurl can discover
the service without a local .proto.
make run CMD='php src/reflection/bin/server.php'
grpcurl -plaintext 127.0.0.1:50051 listMaps a domain rule (amount must be > 0) to INVALID_ARGUMENT with a typed
google.rpc.BadRequest detail. The client receives the status and the decoded
field violations.
make run CMD='php src/rich-errors/bin/server.php' # shell 1
make run CMD='php src/rich-errors/bin/client.php' # shell 2amount -5 -> INVALID_ARGUMENT: payment amount must be positive
payment.amount: got -5, expected a value greater than 0
amount 100 -> OK
The client attaches request headers (x-tenant, x-request-id), the server reads
them from the call metadata and reflects them back through the response body.
make run CMD='php src/metadata/bin/server.php' # shell 1
make run CMD='php src/metadata/bin/client.php' # shell 2server saw: ping [tenant=acme, request-id=req-42]
The server rejects any call without valid credentials with UNAUTHENTICATED.
A client interceptor attaches a bearer token, and the same call then goes through.
make run CMD='php src/auth/bin/server.php' # shell 1
make run CMD='php src/auth/bin/client.php' # shell 2no token -> UNAUTHENTICATED
with token -> OK: ping
The server fails the first two calls with UNAVAILABLE. A client retry interceptor
re-issues the call transparently until the third attempt succeeds.
make run CMD='php src/retry/bin/server.php' # shell 1
make run CMD='php src/retry/bin/client.php' # shell 2ping (served on attempt 3)
All three streaming shapes against one server. Client streaming (LoadPayments)
folds many uploaded payments into one response; server streaming (WatchPayment)
pushes a sequence of events, one every 500ms; bidirectional streaming (Chat)
sends a message and reads its echo, back and forth, over one long-lived call.
make run CMD='php src/streams/bin/server.php' # shell 1
make run CMD='php src/streams/bin/load-client.php' # client streaming
make run CMD='php src/streams/bin/watch-client.php' # server streaming
make run CMD='php src/streams/bin/chat-client.php' # bidirectional streaming# chat-client
hello -> echo: hello
world -> echo: world
bidi -> echo: bidi
Two backends behind a client-side round-robin balancer (ipv4: target with two
addresses); consecutive calls land on alternating backends.
make run CMD='php src/load-balancer/bin/server.php 0.0.0.0:50051' # shell 1
make run CMD='php src/load-balancer/bin/server.php 0.0.0.0:50052' # shell 2
make run CMD='php src/load-balancer/bin/client.php' # shell 3call 1 (from 0.0.0.0:50051)
call 2 (from 0.0.0.0:50052)
call 3 (from 0.0.0.0:50051)
call 4 (from 0.0.0.0:50052)
The standard grpc.health.v1 protocol. The server holds the health state in a
Watchdog and flips one service between SERVING/NOT_SERVING every 3 seconds.
check polls once (like a Kubernetes probe); watch streams every change (what a
client-side load balancer uses to eject and re-add a backend).
make run CMD='php src/health/bin/server.php' # shell 1
make run CMD='php src/health/bin/check.php' # one-shot poll
make run CMD='php src/health/bin/watch.php' # push stream, Ctrl-C to stop# check
sample.v1.EchoService: SERVING
# watch
[14:12:56] NotServing
[14:12:59] Serving
Non-blocking PHP: every call is a fiber, all multiplexed over one HTTP/2 connection, so a fan-out finishes in roughly one round-trip instead of N.
make run CMD='php src/concurrency/bin/server.php' # shell 1
make run CMD='php src/concurrency/bin/client.php' # shell 2sequential: 20 calls in 2230 ms
concurrent: 20 calls in 175 ms
A client deadline propagates to the server as a Cancellation, so an expired
deadline aborts the in-flight handler instead of waiting out the full call.
make run CMD='php src/deadline/bin/server.php' # shell 1
make run CMD='php src/deadline/bin/client.php' # shell 2short (500ms) -> aborted at the deadline (UNAVAILABLE)
long (5s) -> OK: ping
The client and server negotiate gzip; messages are compressed on the wire, transparently to the call.
make run CMD='php src/compression/bin/server.php' # shell 1
make run CMD='php src/compression/bin/client.php' # shell 2payload 140000 B, gzip ~247 B on the wire, echoed 140000 B
An encrypted, verified channel. Generate throwaway certs once with make certs,
then the server presents its certificate and the client verifies it against the CA.
make certs # once
make run CMD='php src/tls/bin/server.php' # shell 1
make run CMD='php src/tls/bin/client.php' # shell 2TLS -> OK: ping over TLS
Mutual TLS: the server also requires the client to present a certificate signed by the trusted CA. A client without one is rejected during the handshake.
make certs # once
make run CMD='php src/mtls/bin/server.php' # shell 1
make run CMD='php src/mtls/bin/client.php' # shell 2no client cert -> rejected (Thesis\Grpc\InvokeError)
with client cert -> OK: ping over mTLS