apache / apache/dubbo-go

[Feature][Triple][Generic] Expose Triple response attachments for generic invocations

Open
#3,445 1 comment 0 reactions 0 assignees View on GitHub
✏️ Feature 3.3.3 help wanted need triage
Dominant language
Go
Stars
5k
Forks
1k
Avg merge
2d 8h
Merged PRs (30d)
31

Description

### Problem

Dubbo-go already supports passing request attachments through `context.WithValue(ctx, constant.AttachmentKey, ...)`. The `dubbo-go-samples/context` sample covers this direction:

```text
consumer request attachment -> provider ctx.Value(constant.AttachmentKey) -> business response body
```

However, this does not cover the opposite direction:

```text
provider result attachments -> Triple response trailers -> consumer reads response attachments
```

For Triple unary calls, provider-side result attachments can be propagated as response trailers. The missing piece is that generic invocations do not currently expose a consumer-side API for reading those response trailers.

### Current limitation

`filter/generic.GenericService` currently defines `Invoke` as a function field without per-call options:

```go
type GenericService struct {
Invoke func(ctx context.Context, methodName string, types []string, args []hessian.Object) (any, error) `dubbo:"$invoke"`
}
```

The normal Triple generated unary client path can capture response metadata with call options, for example:

```go
var trailers http.Header
resp, err := svc.Greet(
ctx,
req,
client.WithResponseTrailer(&trailers),
)
```

But `GenericService.Invoke` has no `opts ...client.CallOption` parameter, so callers cannot pass `client.WithResponseTrailer(&trailers)` when making a generic invocation.

### Expected behavior

Generic Triple unary invocations should provide a way to read response attachments/trailers on the consumer side.

One possible API shape:

```go
var trailers http.Header

result, err := genericService.Invoke(
ctx,
"echo",
[]string{"java.lang.String"},
[]hessian.Object{"hello"},
client.WithResponseTrailer(&trailers),
)
```

`InvokeWithType` should also be able to pass the same call options through:

```go
err := genericService.InvokeWithType(
ctx,
"getUser",
[]string{"java.lang.String"},
[]hessian.Object{"123"},
&user,
client.WithResponseTrailer(&trailers),
)
```

### Suggested implementation direction

- Add `opts ...client.CallOption` to `GenericService.Invoke` and `InvokeWithType`.
- Teach the proxy reflection path to recognize and strip optional `client.CallOption` values from the service method arguments.
- Preserve those call options when constructing the invocation, using the same response metadata attribute path as generated unary clients (`ResponseHeaderKey` / `ResponseTrailerKey`).
- Avoid introducing a second mechanism that reads response trailers back from the original `context.Context`; the existing unary client call option path should be reused.

### Why this matters

Without this, the request attachment path is usable, but generic callers cannot read provider response attachments from Triple response trailers. Documentation should describe the supported direction clearly, and the generic API should expose the same response metadata capture capability available to generated unary clients.

Contributor guide

Open the contributing guide

Research direction

Start with filter/generic.GenericService and trace the proxy reflection path that builds generic invocation arguments. Check how generated Triple unary clients use ResponseHeaderKey, ResponseTrailerKey, and client.CallOption; done means Invoke and InvokeWithType accept the options and a generic consumer can read provider response trailers without using a second context mechanism.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.