int64 support for counters

I’d like to implement an atomic counter. Ideally I can use Client.Add(), but the method does not return the new value of the bin. So I resort to a UDF that increases a number typed bin and return it. However the interface{} returned from Client.Execute() is of type int. How can I make the returned type become int64? Or are there any better way to get int64 counters?

Here is my UDF in case it’s useful:

function add(topRec, intBin, intVal)
        if type(intVal) ~= "number" then
                error("input value is not a number")
        end
        if not aerospike:exists(topRec) then
                aerospike:create(topRec)
        end
        local v = topRec[intBin]
        if v == nil then
                v = intVal
        else
                if type(v) ~= "number" then
                        error("value in the bin is not a number")
                end
                v = v + intVal
        end
        topRec[intBin] = v
        aerospike:update(topRec)
        return v
end

There’s a much better way. You can use Operate command:

  bin := NewBin('atomicCounter', 1) // value can be any integer
  ops := []*Operation{
    GetOp(),
    AddOp(bin),
  }

  rec, err := client.Operate(nil, key, ops...)

Operate command is atomic, and all ops are done in a single transaction.

GetOp() always happens after other operations regardless of the order.

As to your other question:

counter := int64(rec.Bins['atomicCounter].(int))

int is an alias for int64 on 64bit platforms.

1 Like

That’s neat. Thanks!

1 Like

Out of curious, how to get int64 from db on 32 bit platform?

The client is not supported on 32bit platforms.

It seems better to use int64 as strconv.ParseInt() does.

Also looks right now the db (or Go client) does not support storing/fetching uint64? I actually faced this problem and have to encode uint64 into a customized base 64 string. Or I can actually use uint64 as LDT item’s key directly?

Thanks.

You can cast your uint64 into an int64. Values bigger than MaxInt64 will become negative. On retrieval, you can cast them back to uint64.

  u64 := uint64(math.MaxUint64)
  i64 := int64(u64)

  key, err := NewKey(namespace, set, i64)
  client.PutBins(nil, key, NewBin("bin", i64))

  rec, err := client.Get(nil, key)
  fmt.Println(uint64(rec.Bins["bin"].(int)))

I see. That’s a workaround for storage purpose. But it does not work for llist item key which is used for ordering, right?

Haven’t checked, but I’d assume not.