• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / go-tarantool / 22031750625

15 Feb 2026 07:26AM UTC coverage: 74.209% (-0.05%) from 74.257%
22031750625

push

github

oleg-jukovec
future: transformation into interface

Transformed `future` into public `Future` interface,
also `future` become inner implementation.
`setError` and `setResponse` became private methods of inner `future` type.
Added Future benchmarks.
Updated methods and functions with new interface.

43 of 52 new or added lines in 3 files covered. (82.69%)

4 existing lines in 1 file now uncovered.

2978 of 4013 relevant lines covered (74.21%)

10062.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.7
/future.go
1
package tarantool
2

3
import (
4
        "io"
5
        "sync"
6
        "time"
7
)
8

9
// Future is an interface that handle asynchronous request.
10
type Future interface {
11
        Get() ([]interface{}, error)
12
        GetTyped(result interface{}) error
13
        GetResponse() (Response, error)
14
        WaitChan() <-chan struct{}
15
}
16

17
// future is inner implementation of Future interface.
18
type future struct {
19
        requestId uint32
20
        req       Request
21
        next      *future
22
        timeout   time.Duration
23
        mutex     sync.Mutex
24
        resp      Response
25
        err       error
26
        cond      sync.Cond
27
        finished  bool
28
        done      chan struct{}
29
}
30

31
var _ = Future(&future{})
32

33
func (fut *future) wait() {
1,917✔
34
        fut.mutex.Lock()
1,917✔
35
        defer fut.mutex.Unlock()
1,917✔
36

1,917✔
37
        for !fut.finished {
3,036✔
38
                fut.cond.Wait()
1,119✔
39
        }
1,119✔
40
}
41

42
func (fut *future) finish() {
14✔
43
        fut.mutex.Lock()
14✔
44
        defer fut.mutex.Unlock()
14✔
45

14✔
46
        fut.finished = true
14✔
47

14✔
48
        if fut.done != nil {
14✔
49
                close(fut.done)
×
50
        }
×
51

52
        fut.cond.Broadcast()
14✔
53
}
54

55
// NewFutureWithErr returns Future with given error.
56
func NewFutureWithErr(req Request, err error) Future {
4✔
57
        fut := newFuture(req)
4✔
58
        fut.setError(err)
4✔
59
        return fut
4✔
60
}
4✔
61

62
// NewFutureWithResponse returns Future with given Response.
63
func NewFutureWithResponse(req Request, header Header, body io.Reader) (Future, error) {
6✔
64
        fut := newFuture(req)
6✔
65
        if err := fut.setResponse(header, body); err != nil {
6✔
NEW
66
                return nil, err
×
NEW
67
        }
×
68
        return fut, nil
6✔
69
}
70

71
// newFuture creates a new empty future for a given Request.
72
func newFuture(req Request) (fut *future) {
1,893✔
73
        fut = &future{}
1,893✔
74
        fut.done = nil
1,893✔
75
        fut.finished = false
1,893✔
76
        fut.cond.L = &fut.mutex
1,893✔
77
        fut.req = req
1,893✔
78
        return fut
1,893✔
79
}
1,893✔
80

81
func (fut *future) isFinished() bool {
3,745✔
82
        fut.mutex.Lock()
3,745✔
83
        defer fut.mutex.Unlock()
3,745✔
84

3,745✔
85
        return fut.finished
3,745✔
86
}
3,745✔
87

88
// setResponse sets a response for the future and finishes the future.
89
func (fut *future) setResponse(header Header, body io.Reader) error {
1,862✔
90
        fut.mutex.Lock()
1,862✔
91
        defer fut.mutex.Unlock()
1,862✔
92

1,862✔
93
        if fut.finished {
1,862✔
94
                return nil
×
95
        }
×
96

97
        resp, err := fut.req.Response(header, body)
1,862✔
98
        if err != nil {
1,863✔
99
                return err
1✔
100
        }
1✔
101
        fut.resp = resp
1,861✔
102

1,861✔
103
        fut.finished = true
1,861✔
104

1,861✔
105
        if fut.done != nil {
1,861✔
106
                close(fut.done)
×
107
        }
×
108

109
        fut.cond.Broadcast()
1,861✔
110

1,861✔
111
        return nil
1,861✔
112
}
113

114
// setError sets an error for the future and finishes the future.
115
func (fut *future) setError(err error) {
18✔
116
        fut.mutex.Lock()
18✔
117
        defer fut.mutex.Unlock()
18✔
118

18✔
119
        if fut.finished {
18✔
120
                return
×
121
        }
×
122
        fut.err = err
18✔
123

18✔
124
        fut.finished = true
18✔
125

18✔
126
        if fut.done != nil {
18✔
127
                close(fut.done)
×
128
        }
×
129

130
        fut.cond.Broadcast()
18✔
131
}
132

133
// GetResponse waits for Future to be filled and returns Response and error.
134
//
135
// Note: Response could be equal to nil if ClientError is returned in error.
136
//
137
// "error" could be Error, if it is error returned by Tarantool,
138
// or ClientError, if something bad happens in a client process.
139
func (fut *future) GetResponse() (Response, error) {
40✔
140
        fut.wait()
40✔
141
        return fut.resp, fut.err
40✔
142
}
40✔
143

144
// Get waits for Future to be filled and returns the data of the Response and error.
145
//
146
// The data will be []interface{}, so if you want more performance, use GetTyped method.
147
//
148
// "error" could be Error, if it is error returned by Tarantool,
149
// or ClientError, if something bad happens in a client process.
150
func (fut *future) Get() ([]interface{}, error) {
1,217✔
151
        fut.wait()
1,217✔
152
        if fut.err != nil {
1,247✔
153
                return nil, fut.err
30✔
154
        }
30✔
155
        return fut.resp.Decode()
1,187✔
156
}
157

158
// GetTyped waits for Future and calls msgpack.Decoder.Decode(result) if no error happens.
159
// It is could be much faster than Get() function.
160
//
161
// Note: Tarantool usually returns array of tuples (except for Eval and Call17 actions).
162
func (fut *future) GetTyped(result interface{}) error {
660✔
163
        fut.wait()
660✔
164
        if fut.err != nil {
662✔
165
                return fut.err
2✔
166
        }
2✔
167
        return fut.resp.DecodeTyped(result)
658✔
168
}
169

170
var closedChan = make(chan struct{})
171

172
func init() {
1✔
173
        close(closedChan)
1✔
174
}
1✔
175

176
// WaitChan returns channel which becomes closed when response arrived or error occurred.
NEW
177
func (fut *future) WaitChan() <-chan struct{} {
×
178
        fut.mutex.Lock()
×
179
        defer fut.mutex.Unlock()
×
180

×
181
        if fut.finished {
×
182
                return closedChan
×
183
        }
×
184

185
        if fut.done == nil {
×
186
                fut.done = make(chan struct{})
×
187
        }
×
188

189
        return fut.done
×
190
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc