Aerospike Operate API

Not able to read the record via Operate API using aerospike go client . it always returns the generation id only despite adding GET Operation in the Operations List.

Can someone help me here ?

code snippet

func (c *Aerospike) multiBinUpdate(record Record, ttl, generation uint32) (*uint32, error) {
	key, err := c.key(record.GetPK(), record.TableName())
	if err != nil {
		return nil, err
	}
	policy := c.getWritePolicy()
	policy.Expiration = ttl
	policy.GenerationPolicy = aerospike.EXPECT_GEN_EQUAL
	policy.Generation = generation
	var Operations []*aerospike.Operation
	bins := aerospike.Marshal(record, true)
	for _, bin := range bins {
		Operations = append(Operations, aerospike.PutOp(bin))
	}
	Operations = append(Operations, aerospike.GetHeaderOp())
	var rec *aerospike.Record
	if rec, err = c.client.Operate(policy, key, Operations...); err != nil {
		return nil, err
	}
	if rec == nil {
		return nil, errors.New("record is not updated")
	}
	return &rec.Generation, err
}
  1. Sometime it happens that record is not updated and error is also not thrown for the same and application is not able to check if the record is updated or not without error.
  2. if GetOp() is used instead of GetHeaderOp() then it gives parameter error.

Aerospike server version : 5.7

What version of the Go client are you using?

EDIT: Also can you check the server logs to see if there are corresponding lines to the errors you describe here?

@Khosrow_Afroozeh Used aerospike go client latest version and GetOp issue was resolved. However there seems to be an issue with the data updated to aerospike.

issue : Thread1 and Thread 2 is reading the data at same time. first Thread2 update happens and then Thread 1 and there are no Generation error happening in go client.

code snippet

	type record struct {
		Counter *int `as:"counter"`
		PendingTrans []string `as:"pendingTrans"`
		PK *string `as:"pk"`
	}

	func (a *record) GetPK() string {
		return *a.PK
	}

	func (a *record) MultiBinUpdate(generationId uint32) (*uint32, interface{}, error) {
		return aerospike.MultiBinUpdate(a, 0, generationId)
	}

	func (a *record) GetWithHeader() (*uint32, *uint32, error) {
		return aerospike.GetWithHeader(a.GetPK(), a)
	}


func updateAersopike() {
	var a &record{}
	// aerospike data would be stored in record struct
	_, generationId, exrr := record.GetWithHeader()
	if exrr !=nil {
		panic(exrr)
	}

	if record.Counter == nil {
		var b int = 1
		record.Counter = &b
	} else {
		b := *record.Counter + 1
		record.Counter = &b
	}

	// *request.Id is uniq ID
	record.pendingTrans = append(record.pendingTrans, *request.Id)
	newgen, result, err := record.MultiBinUpdate(*generationId)
	if err != nil {
		panic(err)
	}
}




   
func (c *Aerospike) MultiBinUpdate(record Record, ttl, generation uint32) (*uint32, interface{}, error) {
	key, err := c.key(record.GetPK(), record.TableName())
	if err != nil {
		return nil, nil, err
	}
	policy := c.getWritePolicy(UpdatePolicy)
	policy.Expiration = ttl
	policy.GenerationPolicy = aerospike.EXPECT_GEN_EQUAL
	policy.Generation = generation
	var Operations []*aerospike.Operation
	bins := aerospike.Marshal(record, true)
	for _, bin := range bins {
		Operations = append(Operations, aerospike.PutOp(bin))
	}
	Operations = append(Operations, aerospike.GetOp())
	var rec *aerospike.Record
	if rec, err = c.client.Operate(policy, key, Operations...); err != nil {
		return nil, nil, err
	}
	if rec == nil {
		return nil, nil, errors.New("record is not updated")
	}
	return &rec.Generation, &rec.Bins, err
}

@Khosrow_Afroozeh does generation id update happens before record update in aerospike ?

Observations :

Case 1 

inital read with GetHeader 

"2021-11-18T09:40:16.243884316+05:30" sid: [214m8Aci1V9fn4pZ40zTMRj87Wy] generationId: [ 153 ] count: [151]

result from Operate API 

"2021-11-18T09:40:16.244096+05:30" sid: [214m8Aci1V9fn4pZ40zTMRj87Wy] before update generationId:[ 153] after update [154]
Count [152]

read after update using GetHeader 

"2021-11-18T09:40:16.244418205+05:30" sid: [214m8Aci1V9fn4pZ40zTMRj87Wy] generationId: [ 155 ] count: [152] pending transactions: 0


case2 : 

inital read with GetHeader

"2021-11-18T09:40:16.244183055+05:30 sid: [214m873LAqYhcZ3KDM5RF28lVBP] generationId: [ 154 ] count: [151]

result from Operate API 

"2021-11-18T09:40:16.244397088+05:30" sid: [214m873LAqYhcZ3KDM5RF28lVBP] before update generationId:[ 154] after update [155] Count [152]

read after update using GetHeader

"2021-11-18T09:40:16.244559207+05:30" sid: [214m873LAqYhcZ3KDM5RF28lVBP] generationId: [ 155 ] count: [152]

One more interesting fact : I am using the same code with java application as well where I am getting the expected output.

No, the generation update happens under the record lock along with all other metadata and bin updates.

Can you please help me how the above case is happening . I am constantly reproduce the issue with above mentioned code.

@Anil_Kumawat As far as I can tell using your code, the server and the client are working as expected. I need a complete program, not just a part of it, to understand what you are doing and where it’s going wrong.

© 2021 Copyright Aerospike, Inc. | All rights reserved. Creators of the Aerospike Database.