Skip to content
Open
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.

### Changed

* All top-level `New*Request()` constructors now return values instead of
pointers. All methods on request types use value receivers and return
values, enabling immutable builder-style chaining.
* Removed intermediate `spaceRequest`, `spaceIndexRequest` types — `space`
and `index` fields are now inlined directly into each request struct.
The same flattening was applied to `crud.spaceRequest`.
* Required Go version is `1.24` now (#456).
* `test_helpers.MockDoer` is now an interface instead of a struct. The
`Requests` field became a method `Requests()`. The `NewMockDoer()`
Expand Down
31 changes: 31 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,37 @@ TODO
`tarantool.pool` group. When a pool logger is set and a connection
does not have its own logger, the pool passes its logger to each
connection, which then applies its own `WithGroup("tarantool")`.
* All request types (`PingRequest`, `SelectRequest`, `CallRequest`, etc.) now
use value receivers and constructors return values instead of pointers.
Builder methods return modified copies instead of mutating in place.

**Breaking**: calling a builder method without using its return value silently
discards the change:
```Go
// Before (pointer receivers, mutation in place):
req := NewSelectRequest("space")
req.Index("idx") // mutated req directly
conn.Do(req)

// After (value receivers, must use return value):
req := NewSelectRequest("space")
req = req.Index("idx") // must reassign
conn.Do(req)

// Or chain directly:
conn.Do(NewSelectRequest("space").Index("idx"))
```

The same value-receiver pattern was applied to `arrow.InsertRequest` and
`settings.SetRequest`/`settings.GetRequest`.

In the `box` subpackage, request types (`InfoRequest`, `UserExistsRequest`,
`UserCreateRequest`, `SessionSuRequest`, etc.) no longer embed
`tarantool.CallRequest`. They store it as a private field and implement
their own `Context()` method returning the wrapper type. Usage stays clean:
```Go
req := box.NewUserExistsRequest(username).Context(ctx)
```

## Migration from v1.x.x to v2.x.x

Expand Down
18 changes: 9 additions & 9 deletions arrow/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ type InsertRequest struct {
}

// NewInsertRequest returns a new InsertRequest.
func NewInsertRequest(space any, arrow Arrow) *InsertRequest {
return &InsertRequest{
func NewInsertRequest(space any, arrow Arrow) InsertRequest {
return InsertRequest{
space: space,
arrow: arrow,
}
}

// Type returns a IPROTO_INSERT_ARROW type for the request.
func (r *InsertRequest) Type() iproto.Type {
func (r InsertRequest) Type() iproto.Type {
return iproto.IPROTO_INSERT_ARROW
}

// Async returns false to the request return a response.
func (r *InsertRequest) Async() bool {
func (r InsertRequest) Async() bool {
return false
}

// Ctx returns a context of the request.
func (r *InsertRequest) Ctx() context.Context {
func (r InsertRequest) Ctx() context.Context {
return r.ctx
}

Expand All @@ -47,20 +47,20 @@ func (r *InsertRequest) Ctx() context.Context {
// the timeout option for Connection does not affect the lifetime
// of the request. For those purposes use context.WithTimeout() as
// the root context.
func (r *InsertRequest) Context(ctx context.Context) *InsertRequest {
func (r InsertRequest) Context(ctx context.Context) InsertRequest {
r.ctx = ctx
return r
}

// Arrow sets the arrow for insertion the insert arrow request.
// Note: default value is nil.
func (r *InsertRequest) Arrow(arrow Arrow) *InsertRequest {
func (r InsertRequest) Arrow(arrow Arrow) InsertRequest {
r.arrow = arrow
return r
}

// Body fills an msgpack.Encoder with the insert arrow request body.
func (r *InsertRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error {
func (r InsertRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error {
if err := enc.EncodeMapLen(2); err != nil {
return err
}
Expand All @@ -74,7 +74,7 @@ func (r *InsertRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder)
}

// Response creates a response for the InsertRequest.
func (r *InsertRequest) Response(
func (r InsertRequest) Response(
header tarantool.Header,
body io.Reader,
) (tarantool.Response, error) {
Expand Down
17 changes: 12 additions & 5 deletions box/info.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package box

import (
"context"
"fmt"

"github.com/vmihailenco/msgpack/v5"

"github.com/tarantool/go-tarantool/v3"
)

var _ tarantool.Request = (*InfoRequest)(nil)
var _ tarantool.Request = InfoRequest{}

// Info represents detailed information about the Tarantool instance.
// It includes version, node ID, read-only status, process ID, cluster information, and more.
Expand Down Expand Up @@ -112,14 +113,20 @@ func (ir *InfoResponse) DecodeMsgpack(d *msgpack.Decoder) error {
// InfoRequest represents a request to retrieve information about the Tarantool instance.
// It implements the tarantool.Request interface.
type InfoRequest struct {
*tarantool.CallRequest // Underlying Tarantool call request.
baseCallRequest
}

// NewInfoRequest returns a new empty info request.
func NewInfoRequest() InfoRequest {
callReq := tarantool.NewCallRequest("box.info")

return InfoRequest{
callReq,
baseCallRequest: baseCallRequest{
call: tarantool.NewCallRequest("box.info"),
},
}
}

// Context sets a passed context to the request.
func (req InfoRequest) Context(ctx context.Context) InfoRequest {
req.call = req.call.Context(ctx)
return req
}
44 changes: 44 additions & 0 deletions box/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package box

import (
"context"
"io"

"github.com/tarantool/go-iproto"
"github.com/vmihailenco/msgpack/v5"

"github.com/tarantool/go-tarantool/v3"
)

// baseCallRequest wraps a tarantool.CallRequest and implements
// the tarantool.Request interface by delegation.
type baseCallRequest struct {
call tarantool.CallRequest
}

// Type returns IPROTO type for the request.
func (req baseCallRequest) Type() iproto.Type {
return req.call.Type()
}

// Body fills an encoder with the request body.
func (req baseCallRequest) Body(res tarantool.SchemaResolver,
enc *msgpack.Encoder) error {
return req.call.Body(res, enc)
}

// Ctx returns a context of the request.
func (req baseCallRequest) Ctx() context.Context {
return req.call.Ctx()
}

// Async returns whether the request expects a response.
func (req baseCallRequest) Async() bool {
return req.call.Async()
}

// Response creates a response for the request.
func (req baseCallRequest) Response(header tarantool.Header,
body io.Reader) (tarantool.Response, error) {
return req.call.Response(header, body)
}
Loading
Loading