I am trying to write facade code that always keep one (in this example, but maybe more keys but keep in desc by order) in a map in Aerospike.
Here is the facade code:
import com.aerospike.client.Value
import com.aerospike.client.cdt.MapOperation
import com.aerospike.client.cdt.MapOrder
import com.aerospike.client.cdt.MapPolicy
import com.aerospike.client.cdt.MapReturnType
import com.aerospike.client.cdt.MapWriteMode
import com.aerospike.client.query.KeyRecord
import com.aerospike.client.reactor.AerospikeReactorClient
import reactor.core.publisher.Mono
class ForStackOverflow(
private val client: AerospikeReactorClient,
private val keyResolver: KeyResolver
) {
fun updateRuidVersion(key: String, version: Long, time: Long): Mono<KeyRecord> {
val key = getKey(key)
return client.operate(
null,
key,
// Put this version with now time
MapOperation.put(
MapPolicy(MapOrder.KEY_ORDERED, MapWriteMode.UPDATE),
RuidMetadataTablesSchema.LATEST_VERSION_BIN,
Value.get(version),
Value.get(time)
),
// // keep only the latest version
MapOperation.removeByRankRange(
RuidMetadataTablesSchema.LATEST_VERSION_BIN,
-2,1,
MapReturnType.KEY
)
)
}
private fun getKey(key: String) =
keyResolver.getKey(key)
}
Here is the test code that showes that it not deleting by rank - it deletes by last
@Test
fun `trying to keep only last version in table`(){
val client = AerospikeReactorClientBuilder.getAerospikeReactorClient(config)
val writerFacade = ForStackOverflow(
client,
simpleKeyResolver
)
val myId = "id-" + System.currentTimeMillis()
val versions = (0..20).map {it}
val allWrites = versions.reversed().map { version ->
writerFacade.updateRuidVersion(
myId, version.toLong(), System.currentTimeMillis()
)
}
allWrites.forEach{
it.block()
val res = client.get(simpleKeyResolver.getKey(myId)).block()!!
println(res.record.bins[RuidMetadataTablesSchema.LATEST_VERSION_BIN] as TreeMap<Long, Long>)
}
}
and it prints the following:
{20=1716813009091}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{19=1716813009114}
{1=1716813009115}
{1=1716813009115}
I expected it to print only 20= always and not override it with old keys
Rank is by order of value (timestamp in your example) in the key-value pair. If value is same, rank is established by key order. Wondering if adding 1 ms sleep in the loop between each entry would give some clarity. i.e. make the timestamp values unique.
If I am following your code correctly (I reserve the right to be wrong! :-) ) - you insert 20:xx091, then 19:xx114, ( delete 2nd highest rank, deletes 20:xx091), then 18:xx114 (I am suspecting same timestamp value) - so deletes 18:xx114 (same value, then by key order) ... and so on. You were probably able to insert 18: thru 2: with xx114. Then 1:xx115, followed by 0:xx115.
So since we want to keep only the last Key and since the map is being ordered MapPolicy(MapOrder.KEY_ORDERED, MapWriteMode.UPDATE),
then all you need to do is change the operation to removeByIndexRange
meaning it will look like this:
return client.operate(
null,
key,
// Put this version with now time
MapOperation.put(
MapPolicy(MapOrder.KEY_ORDERED, MapWriteMode.UPDATE),
RuidMetadataTablesSchema.LATEST_VERSION_BIN,
Value.get(version),
Value.get(time)
),
// // keep only the latest version
MapOperation.removeByIndexRange(
RuidMetadataTablesSchema.LATEST_VERSION_BIN,
-1,1,
MapReturnType.INVERTED
)
)