Skip to content
Draft
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/reusable-bindings-build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ jobs:
run: |
task generate LIB_PATH=./artifacts/lib${{ env.LIBRARY_NAME }}_x86_64_linux_gnu.a
echo "📁 Generated files:"
find ./generated -type f
echo "📁 slim-bindings-go files:"
find ./slim_bindings -type f
- name: Make sure generation did not modify source files
run: |
Expand All @@ -273,8 +273,8 @@ jobs:
with:
name: go-bindings-generated-code
path: |
./data-plane/bindings/go/generated/**/*.go
./data-plane/bindings/go/generated/**/*.h
./data-plane/bindings/go/slim_bindings
!./data-plane/bindings/go/slim_bindings/*.a
if-no-files-found: error

python-bindings-test:
Expand Down
23 changes: 4 additions & 19 deletions .github/workflows/reusable-go-bindings-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ jobs:
uses: actions/download-artifact@v4
with:
merge-multiple: true
path: ${{ inputs.go-bindings-working-directory }}/generated
path: ${{ inputs.go-bindings-working-directory }}/downloaded_slim_bindings

- name: List downloaded go binding artifacts
run: |
echo "📦 Downloaded artifacts:"
find ./generated -type f -ls
find ./downloaded_slim_bindings -type f -ls

- name: Clone target repository
run: |
Expand All @@ -81,23 +81,8 @@ jobs:
run: |
pushd ./target-repo

# Preserve .git directory and manual files like LICENSE, README
# Remove only the generated files (*.go, *.h, *.a) and cmd directory
rm -f ./*.go ./*.h ./*.a
rm -rf ./cmd

# Copy generated Go bindings (excluding .a files)
cp ../generated/${{ env.LIBRARY_NAME }}/*.{go,h} ./

# Copy CLI tool (self-contained, includes download logic)
mkdir -p ./cmd/slim-bindings-setup
cp ../release-files/cmd/slim-bindings-setup/main.go ./cmd/slim-bindings-setup/

# Create go.mod if it doesn't exist
if [ ! -f go.mod ]; then
echo "📦 Creating go.mod for target repository..."
go mod init github.com/${{ env.GO_BINDINGS_REPO }}
fi
# Copy Go bindings
cp -r ../downloaded_slim_bindings/* ./

# Show what will be committed
echo "📋 Files to be committed:"
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,5 @@ control-plane/control-plane/db/controlplane.db
**/*.a
artifacts

# Go bindings generated code
data-plane/bindings/go/generated

libslim_bindings.dylib
libslim_bindings.a
2 changes: 1 addition & 1 deletion data-plane/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions data-plane/bindings/go/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
slim_bindings/slim_bindings.go
slim_bindings/slim_bindings.h
slim_bindings/*.a
44 changes: 34 additions & 10 deletions data-plane/bindings/go/Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ includes:
rust:
taskfile: ../../../tasks/rust.yaml
internal: true
tools:
taskfile: ../../../tasks/tools.yaml
internal: true
flatten: true

vars:
BINDINGS_DIR: "{{.TASKFILE_DIR}}/../rust"
Expand Down Expand Up @@ -40,7 +44,7 @@ tasks:
cmds:
- echo "🔧 Patching cgo directives..."
- |
GO_FILE="generated/{{.LIB_NAME}}/{{.LIB_NAME}}.go"
GO_FILE="slim_bindings/{{.LIB_NAME}}.go"
if [ -f "$GO_FILE" ]; then
# Create the new cgo preamble with static LDFLAGS placeholders
cat > /tmp/cgo_preamble.txt << 'EOF'
Expand Down Expand Up @@ -79,7 +83,7 @@ tasks:
cmds:
- echo "🔧 Patching slim_bindings.h..."
- |
HEADER_FILE="generated/{{.LIB_NAME}}/{{.LIB_NAME}}.h"
HEADER_FILE="slim_bindings/{{.LIB_NAME}}.h"
if [ -f "$HEADER_FILE" ]; then
# Check if patch is already applied
if grep -q "#ifdef _WIN32" "$HEADER_FILE" && grep -q "__declspec(dllexport) void slim_bindings_uniffiFutureContinuationCallback" "$HEADER_FILE"; then
Expand Down Expand Up @@ -124,12 +128,11 @@ tasks:
- |
uniffi-bindgen-go \
--library '{{.LIB_PATH}}' \
--out-dir generated
- cd generated && go mod init github.com/agntcy/slim/bindings/generated 2>/dev/null || true && go mod edit -go=1.25
--out-dir '.' \
- task: copy-library
- task: patch-header
- task: patch-cgo-directives
- echo "✅ Bindings generated in generated/"
- echo "✅ Bindings generated in slim_bindings/"
silent: true

install-uniffi-bindgen-go:
Expand All @@ -148,7 +151,7 @@ tasks:
- echo "📦 Copying static libraries..."
- |
LIB_DIR=$(dirname "{{.LIB_PATH}}")
DEST_DIR="generated/{{.LIB_NAME}}"
DEST_DIR="slim_bindings"

# Check if libraries already have platform-specific names (from CI build)
PLATFORM_LIBS=$(find "$LIB_DIR" -type f \( -name "lib{{.LIB_NAME}}_*.a" -o -name "{{.LIB_NAME}}_*.lib" \) 2>/dev/null | head -1)
Expand Down Expand Up @@ -199,10 +202,29 @@ tasks:
exit 1
fi
fi
- echo "✅ Libraries in generated/{{.LIB_NAME}}/:"
- ls -lah "generated/{{.LIB_NAME}}/"*{{.LIB_NAME}}*.a "generated/{{.LIB_NAME}}/"*{{.LIB_NAME}}*.lib 2>/dev/null || echo " (no library files found)"
- echo "✅ Libraries in slim_bindings/:"
- ls -lah "slim_bindings/"*{{.LIB_NAME}}*.a "slim_bindings/"*{{.LIB_NAME}}*.lib 2>/dev/null || echo " (no library files found)"
silent: true

generate-proto:
desc: "Generate proto files for the Python bindings"
deps:
- task: rust:toolchain:run-command
vars:
COMMAND: |
cargo build --package agntcy-protoc-slimrpc-plugin --bin protoc-gen-slimrpc-go --release
- task: tools:buf
cmds:
- |
# Find all the buf.gen.yaml files in the current directory and its subdirectories
find . -name 'buf.gen.yaml' | while read -r file; do
# Generate the proto files using buf
echo "Generating proto files for $file"
# get folder name
folder=$(dirname "$file")
pushd > /dev/null ${folder} && {{.TOOLS_INSTALL_DIR}}/buf generate && popd > /dev/null
done

test:
desc: Run all tests
deps:
Expand Down Expand Up @@ -231,7 +253,9 @@ tasks:
cmds:
- echo "🧹 Cleaning build artifacts..."
- cd {{.BINDINGS_DIR}} && cargo clean
- rm -rf generated/
- rm slim_bindings/slim_bindings.go || true
- rm slim_bindings/slim_bindings.h || true
- rm slim_bindings/libslim_bindings_*.a || true
- echo "✅ Clean complete"
silent: true

Expand All @@ -242,7 +266,7 @@ tasks:
- task: adapter:bindings:build:all
vars:
PROFILE: release
dir: cmd/server
dir: examples/server
cmds:
- echo "🚀 Starting SLIM server..."
- go run . {{.CLI_ARGS}}
Expand Down
7 changes: 0 additions & 7 deletions data-plane/bindings/go/cmd/server/go.mod

This file was deleted.

2 changes: 1 addition & 1 deletion data-plane/bindings/go/examples/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"fmt"
"strings"

slim "github.com/agntcy/slim/bindings/generated/slim_bindings"
slim "github.com/agntcy/slim-bindings-go"
)

// Default configuration values
Expand Down
2 changes: 1 addition & 1 deletion data-plane/bindings/go/examples/group/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"sync"
"time"

slim "github.com/agntcy/slim/bindings/generated/slim_bindings"
slim "github.com/agntcy/slim-bindings-go"
"github.com/agntcy/slim/bindings/go/examples/common"
)

Expand Down
2 changes: 1 addition & 1 deletion data-plane/bindings/go/examples/point_to_point/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"log"
"time"

slim "github.com/agntcy/slim/bindings/generated/slim_bindings"
slim "github.com/agntcy/slim-bindings-go"
"github.com/agntcy/slim/bindings/go/examples/common"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"syscall"
"time"

slim "github.com/agntcy/slim/bindings/generated/slim_bindings"
slim "github.com/agntcy/slim-bindings-go"
)

func main() {
Expand Down
156 changes: 156 additions & 0 deletions data-plane/bindings/go/examples/slimrpc/simple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# slimrpc Simple Example (Go)

This example demonstrates all slimrpc RPC patterns in Go with comprehensive client and server implementations.

## Prerequisites

- Go 1.21+
- Running SLIM server on `localhost:46357`
- `buf` CLI tool installed

## Generate Code

```bash
buf generate
```

This generates:
- `types/example.pb.go` - Standard protobuf types
- `types/example_slimrpc.pb.go` - slimrpc client and server stubs

## Run the Example

In one terminal, start the server:

```bash
go run cmd/server/server.go
```

In another terminal, run the client:

```bash
go run cmd/client/client.go
```

## Code Structure

### Server (`cmd/server/server.go`)

Implements all four RPC patterns:

1. **UnaryUnary**: Simple request-response
2. **UnaryStream**: Single request, multiple responses
3. **StreamUnary**: Multiple requests, single response
4. **StreamStream**: Bidirectional streaming

The server implements the `TestServer` interface and embeds `UnimplementedTestServer` for forward compatibility.

### Client (`cmd/client/client.go`)

Demonstrates all four RPC patterns:

#### 1. Unary-Unary
```go
response, err := client.ExampleUnaryUnary(ctx, request)
```

#### 2. Unary-Stream (Server Streaming)
```go
stream, err := client.ExampleUnaryStream(ctx, request)
for {
resp, err := stream.Recv()
if resp == nil { break }
// Process response
}
```

#### 3. Stream-Unary (Client Streaming)
```go
stream, err := client.ExampleStreamUnary(ctx)
for i := 0; i < 10; i++ {
stream.Send(request)
}
response, err := stream.CloseAndRecv()
```

#### 4. Stream-Stream (Bidirectional Streaming)
```go
stream, err := client.ExampleStreamStream(ctx)

// Send in goroutine
go func() {
for i := 0; i < 10; i++ {
stream.Send(request)
}
stream.CloseSend()
}()

// Receive
for {
resp, err := stream.Recv()
if resp == nil { break }
// Process response
}
```

## Generated Code

The `buf generate` command produces type-safe interfaces for all RPC patterns:

### Client Interface
```go
type TestClient interface {
ExampleUnaryUnary(ctx context.Context, req *ExampleRequest) (*ExampleResponse, error)
ExampleUnaryStream(ctx context.Context, req *ExampleRequest) (Test_ExampleUnaryStreamClient, error)
ExampleStreamUnary(ctx context.Context) (Test_ExampleStreamUnaryClient, error)
ExampleStreamStream(ctx context.Context) (Test_ExampleStreamStreamClient, error)
}
```

### Server Interface
```go
type TestServer interface {
ExampleUnaryUnary(ctx context.Context, req *ExampleRequest) (*ExampleResponse, error)
ExampleUnaryStream(req *ExampleRequest, stream Test_ExampleUnaryStreamServer) error
ExampleStreamUnary(stream Test_ExampleStreamUnaryServer) error
ExampleStreamStream(stream Test_ExampleStreamStreamServer) error
}
```

### Stream Interfaces
Each streaming method gets its own interface with `Send()` and/or `Recv()` methods:

```go
// Server streaming
type Test_ExampleUnaryStreamServer interface {
Send(*ExampleResponse) error
}

// Client streaming
type Test_ExampleStreamUnaryServer interface {
Recv() (*ExampleRequest, error)
}

// Bidirectional streaming
type Test_ExampleStreamStreamServer interface {
Send(*ExampleResponse) error
Recv() (*ExampleRequest, error)
}
```

## Features

- ✅ All 4 RPC patterns (unary-unary, unary-stream, stream-unary, stream-stream)
- ✅ Type-safe client and server interfaces
- ✅ Automatic serialization/deserialization
- ✅ Proper error handling with RPC error conversion
- ✅ Stream end detection (nil return)
- ✅ Forward-compatible server with unimplemented method stubs
- ✅ Concurrent send/receive for bidirectional streaming

## Notes

- `Recv()` returns `nil` when the stream ends (not an error)
- Error handling automatically converts `RpcError` to standard Go errors
- Bidirectional streaming uses goroutines for concurrent send/receive
- The server automatically closes response streams when handlers return
Loading
Loading