313 lines
9 KiB
Go
313 lines
9 KiB
Go
package gocb
|
|
|
|
import (
|
|
"time"
|
|
|
|
gocbcore "github.com/couchbase/gocbcore/v9"
|
|
)
|
|
|
|
// BinaryCollection is a set of binary operations.
|
|
type BinaryCollection struct {
|
|
collection *Collection
|
|
}
|
|
|
|
// AppendOptions are the options available to the Append operation.
|
|
type AppendOptions struct {
|
|
Timeout time.Duration
|
|
DurabilityLevel DurabilityLevel
|
|
PersistTo uint
|
|
ReplicateTo uint
|
|
Cas Cas
|
|
RetryStrategy RetryStrategy
|
|
}
|
|
|
|
func (c *Collection) binaryAppend(id string, val []byte, opts *AppendOptions) (mutOut *MutationResult, errOut error) {
|
|
if opts == nil {
|
|
opts = &AppendOptions{}
|
|
}
|
|
|
|
opm := c.newKvOpManager("Append", nil)
|
|
defer opm.Finish()
|
|
|
|
opm.SetDocumentID(id)
|
|
opm.SetDuraOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
|
|
opm.SetRetryStrategy(opts.RetryStrategy)
|
|
opm.SetTimeout(opts.Timeout)
|
|
|
|
if err := opm.CheckReadyForOp(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agent, err := c.getKvProvider()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = opm.Wait(agent.Append(gocbcore.AdjoinOptions{
|
|
Key: opm.DocumentID(),
|
|
Value: val,
|
|
CollectionName: opm.CollectionName(),
|
|
ScopeName: opm.ScopeName(),
|
|
DurabilityLevel: opm.DurabilityLevel(),
|
|
DurabilityLevelTimeout: opm.DurabilityTimeout(),
|
|
Cas: gocbcore.Cas(opts.Cas),
|
|
RetryStrategy: opm.RetryStrategy(),
|
|
TraceContext: opm.TraceSpan(),
|
|
Deadline: opm.Deadline(),
|
|
}, func(res *gocbcore.AdjoinResult, err error) {
|
|
if err != nil {
|
|
errOut = opm.EnhanceErr(err)
|
|
opm.Reject()
|
|
return
|
|
}
|
|
|
|
mutOut = &MutationResult{}
|
|
mutOut.cas = Cas(res.Cas)
|
|
mutOut.mt = opm.EnhanceMt(res.MutationToken)
|
|
|
|
opm.Resolve(mutOut.mt)
|
|
}))
|
|
if err != nil {
|
|
errOut = err
|
|
}
|
|
return
|
|
}
|
|
|
|
// Append appends a byte value to a document.
|
|
func (c *BinaryCollection) Append(id string, val []byte, opts *AppendOptions) (mutOut *MutationResult, errOut error) {
|
|
return c.collection.binaryAppend(id, val, opts)
|
|
}
|
|
|
|
// PrependOptions are the options available to the Prepend operation.
|
|
type PrependOptions struct {
|
|
Timeout time.Duration
|
|
DurabilityLevel DurabilityLevel
|
|
PersistTo uint
|
|
ReplicateTo uint
|
|
Cas Cas
|
|
RetryStrategy RetryStrategy
|
|
}
|
|
|
|
func (c *Collection) binaryPrepend(id string, val []byte, opts *PrependOptions) (mutOut *MutationResult, errOut error) {
|
|
if opts == nil {
|
|
opts = &PrependOptions{}
|
|
}
|
|
|
|
opm := c.newKvOpManager("Prepend", nil)
|
|
defer opm.Finish()
|
|
|
|
opm.SetDocumentID(id)
|
|
opm.SetDuraOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
|
|
opm.SetRetryStrategy(opts.RetryStrategy)
|
|
opm.SetTimeout(opts.Timeout)
|
|
|
|
if err := opm.CheckReadyForOp(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agent, err := c.getKvProvider()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = opm.Wait(agent.Prepend(gocbcore.AdjoinOptions{
|
|
Key: opm.DocumentID(),
|
|
Value: val,
|
|
CollectionName: opm.CollectionName(),
|
|
ScopeName: opm.ScopeName(),
|
|
DurabilityLevel: opm.DurabilityLevel(),
|
|
DurabilityLevelTimeout: opm.DurabilityTimeout(),
|
|
Cas: gocbcore.Cas(opts.Cas),
|
|
RetryStrategy: opm.RetryStrategy(),
|
|
TraceContext: opm.TraceSpan(),
|
|
Deadline: opm.Deadline(),
|
|
}, func(res *gocbcore.AdjoinResult, err error) {
|
|
if err != nil {
|
|
errOut = opm.EnhanceErr(err)
|
|
opm.Reject()
|
|
return
|
|
}
|
|
|
|
mutOut = &MutationResult{}
|
|
mutOut.cas = Cas(res.Cas)
|
|
mutOut.mt = opm.EnhanceMt(res.MutationToken)
|
|
|
|
opm.Resolve(mutOut.mt)
|
|
}))
|
|
if err != nil {
|
|
errOut = err
|
|
}
|
|
return
|
|
}
|
|
|
|
// Prepend prepends a byte value to a document.
|
|
func (c *BinaryCollection) Prepend(id string, val []byte, opts *PrependOptions) (mutOut *MutationResult, errOut error) {
|
|
return c.collection.binaryPrepend(id, val, opts)
|
|
}
|
|
|
|
// IncrementOptions are the options available to the Increment operation.
|
|
type IncrementOptions struct {
|
|
Timeout time.Duration
|
|
// Expiry is the length of time that the document will be stored in Couchbase.
|
|
// A value of 0 will set the document to never expire.
|
|
Expiry time.Duration
|
|
// Initial, if non-negative, is the `initial` value to use for the document if it does not exist.
|
|
// If present, this is the value that will be returned by a successful operation.
|
|
Initial int64
|
|
// Delta is the value to use for incrementing/decrementing if Initial is not present.
|
|
Delta uint64
|
|
DurabilityLevel DurabilityLevel
|
|
PersistTo uint
|
|
ReplicateTo uint
|
|
Cas Cas
|
|
RetryStrategy RetryStrategy
|
|
}
|
|
|
|
func (c *Collection) binaryIncrement(id string, opts *IncrementOptions) (countOut *CounterResult, errOut error) {
|
|
if opts == nil {
|
|
opts = &IncrementOptions{}
|
|
}
|
|
|
|
opm := c.newKvOpManager("Increment", nil)
|
|
defer opm.Finish()
|
|
|
|
opm.SetDocumentID(id)
|
|
opm.SetDuraOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
|
|
opm.SetRetryStrategy(opts.RetryStrategy)
|
|
opm.SetTimeout(opts.Timeout)
|
|
|
|
realInitial := uint64(0xFFFFFFFFFFFFFFFF)
|
|
if opts.Initial >= 0 {
|
|
realInitial = uint64(opts.Initial)
|
|
}
|
|
|
|
if err := opm.CheckReadyForOp(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agent, err := c.getKvProvider()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = opm.Wait(agent.Increment(gocbcore.CounterOptions{
|
|
Key: opm.DocumentID(),
|
|
Delta: opts.Delta,
|
|
Initial: realInitial,
|
|
Expiry: durationToExpiry(opts.Expiry),
|
|
CollectionName: opm.CollectionName(),
|
|
ScopeName: opm.ScopeName(),
|
|
DurabilityLevel: opm.DurabilityLevel(),
|
|
DurabilityLevelTimeout: opm.DurabilityTimeout(),
|
|
Cas: gocbcore.Cas(opts.Cas),
|
|
RetryStrategy: opm.RetryStrategy(),
|
|
TraceContext: opm.TraceSpan(),
|
|
Deadline: opm.Deadline(),
|
|
}, func(res *gocbcore.CounterResult, err error) {
|
|
if err != nil {
|
|
errOut = opm.EnhanceErr(err)
|
|
opm.Reject()
|
|
return
|
|
}
|
|
|
|
countOut = &CounterResult{}
|
|
countOut.cas = Cas(res.Cas)
|
|
countOut.mt = opm.EnhanceMt(res.MutationToken)
|
|
countOut.content = res.Value
|
|
|
|
opm.Resolve(countOut.mt)
|
|
}))
|
|
if err != nil {
|
|
errOut = err
|
|
}
|
|
return
|
|
}
|
|
|
|
// Increment performs an atomic addition for an integer document. Passing a
|
|
// non-negative `initial` value will cause the document to be created if it did not
|
|
// already exist.
|
|
func (c *BinaryCollection) Increment(id string, opts *IncrementOptions) (countOut *CounterResult, errOut error) {
|
|
return c.collection.binaryIncrement(id, opts)
|
|
}
|
|
|
|
// DecrementOptions are the options available to the Decrement operation.
|
|
type DecrementOptions struct {
|
|
Timeout time.Duration
|
|
// Expiry is the length of time that the document will be stored in Couchbase.
|
|
// A value of 0 will set the document to never expire.
|
|
Expiry time.Duration
|
|
// Initial, if non-negative, is the `initial` value to use for the document if it does not exist.
|
|
// If present, this is the value that will be returned by a successful operation.
|
|
Initial int64
|
|
// Delta is the value to use for incrementing/decrementing if Initial is not present.
|
|
Delta uint64
|
|
DurabilityLevel DurabilityLevel
|
|
PersistTo uint
|
|
ReplicateTo uint
|
|
Cas Cas
|
|
RetryStrategy RetryStrategy
|
|
}
|
|
|
|
func (c *Collection) binaryDecrement(id string, opts *DecrementOptions) (countOut *CounterResult, errOut error) {
|
|
if opts == nil {
|
|
opts = &DecrementOptions{}
|
|
}
|
|
|
|
opm := c.newKvOpManager("Decrement", nil)
|
|
defer opm.Finish()
|
|
|
|
opm.SetDocumentID(id)
|
|
opm.SetDuraOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
|
|
opm.SetRetryStrategy(opts.RetryStrategy)
|
|
opm.SetTimeout(opts.Timeout)
|
|
|
|
realInitial := uint64(0xFFFFFFFFFFFFFFFF)
|
|
if opts.Initial >= 0 {
|
|
realInitial = uint64(opts.Initial)
|
|
}
|
|
|
|
if err := opm.CheckReadyForOp(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agent, err := c.getKvProvider()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = opm.Wait(agent.Decrement(gocbcore.CounterOptions{
|
|
Key: opm.DocumentID(),
|
|
Delta: opts.Delta,
|
|
Initial: realInitial,
|
|
Expiry: durationToExpiry(opts.Expiry),
|
|
CollectionName: opm.CollectionName(),
|
|
ScopeName: opm.ScopeName(),
|
|
DurabilityLevel: opm.DurabilityLevel(),
|
|
DurabilityLevelTimeout: opm.DurabilityTimeout(),
|
|
Cas: gocbcore.Cas(opts.Cas),
|
|
RetryStrategy: opm.RetryStrategy(),
|
|
TraceContext: opm.TraceSpan(),
|
|
Deadline: opm.Deadline(),
|
|
}, func(res *gocbcore.CounterResult, err error) {
|
|
if err != nil {
|
|
errOut = opm.EnhanceErr(err)
|
|
opm.Reject()
|
|
return
|
|
}
|
|
|
|
countOut = &CounterResult{}
|
|
countOut.cas = Cas(res.Cas)
|
|
countOut.mt = opm.EnhanceMt(res.MutationToken)
|
|
countOut.content = res.Value
|
|
|
|
opm.Resolve(countOut.mt)
|
|
}))
|
|
if err != nil {
|
|
errOut = err
|
|
}
|
|
return
|
|
}
|
|
|
|
// Decrement performs an atomic subtraction for an integer document. Passing a
|
|
// non-negative `initial` value will cause the document to be created if it did not
|
|
// already exist.
|
|
func (c *BinaryCollection) Decrement(id string, opts *DecrementOptions) (countOut *CounterResult, errOut error) {
|
|
return c.collection.binaryDecrement(id, opts)
|
|
}
|