This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/skywalking-banyandb-java-client.git


The following commit(s) were added to refs/heads/main by this push:
     new 5548fea  Add property's ttl (#48)
5548fea is described below

commit 5548feaceb857a00ff2c907804d936be5edc7aef
Author: Gao Hongtao <hanahm...@gmail.com>
AuthorDate: Mon Sep 18 10:55:09 2023 +0800

    Add property's ttl (#48)
---
 CHANGES.md                                         |  1 +
 README.md                                          | 17 ++++++++++
 .../banyandb/v1/client/BanyanDBClient.java         | 10 ++++++
 .../banyandb/v1/client/metadata/Property.java      | 32 +++++++++++++++++--
 .../banyandb/v1/client/metadata/PropertyStore.java | 12 ++++++-
 src/main/proto/banyandb/v1/banyandb-property.proto | 16 ++++++++++
 .../banyandb/v1/client/BanyanDBClientTestCI.java   |  2 +-
 .../v1/client/ITBanyanDBPropertyTests.java         | 13 ++++++++
 .../v1/client/metadata/PropertyStoreTest.java      | 37 ++++++++++++++++++++--
 9 files changed, 133 insertions(+), 7 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 8f80e2a..dbe9ec8 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,6 +8,7 @@ Release Notes.
 ### Features
 
 * Add mod revision check to write requests
+* Add TTL to property.
 
 0.4.0
 ------------------
diff --git a/README.md b/README.md
index 4da8175..ab78a18 100644
--- a/README.md
+++ b/README.md
@@ -323,6 +323,23 @@ Property property = Property.create("default", "sw", 
"ui_template")
 this.client.apply(property); //created:false tagsNum:1
 ```
 
+The property supports setting TTL.
+
+```java
+Property property = Property.create("default", "sw", "temp_date")
+    .addTag(TagAndValue.newStringTag("state", "failed"))
+    .ttl("30m")
+    .build();
+this.client.apply(property); //created:false tagsNum:1 lease_id:1
+```
+The property's TTL can be extended by calling `Client.keepAliveProperty`,
+
+```java
+this.client.keepAliveProperty(1); //lease_id:1
+```
+
+The property's live time is reset to 30 minutes.
+
 ### Query
 
 Property can be queried via `Client.findProperty`,
diff --git 
a/src/main/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClient.java 
b/src/main/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClient.java
index bd33d8f..69a04f9 100644
--- a/src/main/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClient.java
+++ b/src/main/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClient.java
@@ -544,6 +544,16 @@ public class BanyanDBClient implements Closeable {
         return store.delete(group, name, id, tags);
     }
 
+    /**
+     * Keep alive the property
+     *
+     * @param leaseId lease id of the property
+     */
+    public void keepAliveProperty(long leaseId) throws BanyanDBException {
+        PropertyStore store = new PropertyStore(checkNotNull(this.channel));
+        store.keepAlive(leaseId);
+    }
+
     /**
      * Bind index rule to the stream
      *
diff --git 
a/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/Property.java 
b/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/Property.java
index 72771e5..a35536e 100644
--- 
a/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/Property.java
+++ 
b/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/Property.java
@@ -19,12 +19,15 @@
 package org.apache.skywalking.banyandb.v1.client.metadata;
 
 import com.google.auto.value.AutoValue;
+import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import org.apache.skywalking.banyandb.model.v1.BanyandbModel;
 import org.apache.skywalking.banyandb.property.v1.BanyandbProperty;
 import org.apache.skywalking.banyandb.v1.client.TagAndValue;
+import org.apache.skywalking.banyandb.v1.client.util.IgnoreHashEquals;
 import org.apache.skywalking.banyandb.v1.client.util.TimeUtils;
 
+import javax.annotation.Nullable;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.List;
@@ -35,19 +38,32 @@ public abstract class Property extends 
NamedSchema<BanyandbProperty.Property> {
 
     public abstract ImmutableList<TagAndValue<?>> tags();
 
+    @Nullable
+    public abstract String ttl();
+
+    @Nullable
+    @IgnoreHashEquals
+    public abstract Long leaseId();
+
     @Override
     public BanyandbProperty.Property serialize() {
         List<BanyandbModel.Tag> tags = new ArrayList<>(this.tags().size());
         for (final TagAndValue<?> tagAndValue : this.tags()) {
             tags.add(tagAndValue.build());
         }
-        return BanyandbProperty.Property.newBuilder()
+        BanyandbProperty.Property.Builder builder = 
BanyandbProperty.Property.newBuilder()
                 .setMetadata(BanyandbProperty.Metadata.newBuilder()
                         .setId(id())
                         .setContainer(buildMetadata())
                         .build())
-                .addAllTags(tags)
-                .build();
+                .addAllTags(tags);
+        if (!Strings.isNullOrEmpty(ttl())) {
+            builder.setTtl(ttl());
+        }
+        if (leaseId() != null) {
+            builder.setLeaseId(leaseId());
+        }
+        return builder.build();
     }
 
     public static Builder create(String group, String name, String id) {
@@ -59,6 +75,12 @@ public abstract class Property extends 
NamedSchema<BanyandbProperty.Property> {
                         pb.getMetadata().getContainer().getName(),
                         pb.getMetadata().getId())
                 .setUpdatedAt(TimeUtils.parseTimestamp(pb.getUpdatedAt()));
+        if (!Strings.isNullOrEmpty(pb.getTtl())) {
+            b.setTtl(pb.getTtl());
+        }
+        if (pb.getLeaseId() > 0) {
+            b.setLeaseId(pb.getLeaseId());
+        }
 
         // build tag family spec
         for (int i = 0; i < pb.getTagsCount(); i++) {
@@ -85,6 +107,10 @@ public abstract class Property extends 
NamedSchema<BanyandbProperty.Property> {
             return this;
         }
 
+        public abstract Builder setTtl(String ttl);
+
+        abstract Builder setLeaseId(long leaseId);
+
         public abstract Property build();
     }
 }
diff --git 
a/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStore.java
 
b/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStore.java
index c75ebf8..bc34452 100644
--- 
a/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStore.java
+++ 
b/src/main/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStore.java
@@ -57,7 +57,7 @@ public class PropertyStore {
                 .build();
         BanyandbProperty.ApplyResponse resp = 
HandleExceptionsWith.callAndTranslateApiException(() ->
                 this.stub.apply(r));
-        return new AutoValue_PropertyStore_ApplyResult(resp.getCreated(), 
resp.getTagsNum());
+        return new AutoValue_PropertyStore_ApplyResult(resp.getCreated(), 
resp.getTagsNum(), resp.getLeaseId());
     }
 
     public DeleteResult delete(String group, String name, String id, String... 
tags) throws BanyanDBException {
@@ -115,6 +115,14 @@ public class PropertyStore {
         return 
resp.getPropertyList().stream().map(Property::fromProtobuf).collect(Collectors.toList());
     }
 
+    public void keepAlive(long leaseId) throws BanyanDBException {
+        BanyandbProperty.KeepAliveRequest req = 
BanyandbProperty.KeepAliveRequest.newBuilder()
+                .setLeaseId(leaseId)
+                .build();
+        HandleExceptionsWith.callAndTranslateApiException(() ->
+                this.stub.keepAlive(req));
+    }
+
     public enum Strategy {
         MERGE, REPLACE
     }
@@ -124,6 +132,8 @@ public class PropertyStore {
         public abstract boolean created();
 
         public abstract int tagsNum();
+
+        public abstract long leaseId();
     }
 
     @AutoValue
diff --git a/src/main/proto/banyandb/v1/banyandb-property.proto 
b/src/main/proto/banyandb/v1/banyandb-property.proto
index d2bb04c..73299a0 100644
--- a/src/main/proto/banyandb/v1/banyandb-property.proto
+++ b/src/main/proto/banyandb/v1/banyandb-property.proto
@@ -34,6 +34,7 @@ message Metadata {
   string id = 2;
 }
 
+
 // Property stores the user defined data
 message Property {
   // metadata is the identity of a property
@@ -42,6 +43,13 @@ message Property {
   repeated model.v1.Tag tags = 2;
   // updated_at indicates when the property is updated
   google.protobuf.Timestamp updated_at = 3;
+  // readonly. lease_id is the ID of the lease that attached to key.
+  int64 lease_id = 4;
+  // ttl indicates the time to live of the property.
+  // It's a string in the format of "1h", "2m", "3s", "1500ms".
+  // It defaults to 0s, which means the property never expires.
+  // The minimum allowed ttl is 1s.
+  string ttl = 5;
 }
 
 message ApplyRequest {
@@ -60,6 +68,7 @@ message ApplyResponse {
   // True: the property is absent. False: the property existed.
   bool created = 1;
   uint32 tags_num = 2;
+  int64 lease_id = 3;
 }
 
 message DeleteRequest {
@@ -91,10 +100,17 @@ message ListResponse {
   repeated banyandb.property.v1.Property property = 1;
 }
 
+message KeepAliveRequest {
+  int64 lease_id = 1;
+}
+
+message KeepAliveResponse {}
+
 service PropertyService {
   // Apply creates a property if it's absent, or update a existed one based on 
a strategy.
   rpc Apply(ApplyRequest) returns (ApplyResponse);
   rpc Delete(DeleteRequest) returns (DeleteResponse);
   rpc Get(GetRequest) returns (GetResponse);
   rpc List(ListRequest) returns (ListResponse);
+  rpc KeepAlive(KeepAliveRequest) returns (KeepAliveResponse);
 }
diff --git 
a/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
 
b/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
index b107273..e34c6c1 100644
--- 
a/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
+++ 
b/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
@@ -30,7 +30,7 @@ import java.io.IOException;
 public class BanyanDBClientTestCI {
     private static final String REGISTRY = "ghcr.io";
     private static final String IMAGE_NAME = "apache/skywalking-banyandb";
-    private static final String TAG = 
"9552688d60f055f6bb539a91464e8b1db77e7309";
+    private static final String TAG = 
"f3abf75e66695f3c9fcae3138ad55e7a9d74f39a";
 
     private static final String IMAGE = REGISTRY + "/" + IMAGE_NAME + ":" + 
TAG;
 
diff --git 
a/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBPropertyTests.java
 
b/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBPropertyTests.java
index f3524d4..40c55f7 100644
--- 
a/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBPropertyTests.java
+++ 
b/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBPropertyTests.java
@@ -22,6 +22,7 @@ import io.grpc.Status;
 import 
org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException;
 import org.apache.skywalking.banyandb.v1.client.metadata.Group;
 import org.apache.skywalking.banyandb.v1.client.metadata.Property;
+import org.apache.skywalking.banyandb.v1.client.metadata.PropertyStore;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -128,4 +129,16 @@ public class ITBanyanDBPropertyTests extends 
BanyanDBClientTestCI {
         });
     }
 
+    @Test
+    public void test_PropertyKeepAlive() throws BanyanDBException {
+        Property property = Property.create("default", "sw", "id1")
+                .setTtl("30m")
+                .addTag(TagAndValue.newStringTag("name", "bar"))
+                .build();
+        PropertyStore.ApplyResult resp = this.client.apply(property);
+        Assert.assertTrue(resp.created());
+        Assert.assertTrue(resp.leaseId() > 0);
+        this.client.keepAliveProperty(resp.leaseId());
+    }
+
 }
diff --git 
a/src/test/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStoreTest.java
 
b/src/test/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStoreTest.java
index ad31872..d770ca2 100644
--- 
a/src/test/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStoreTest.java
+++ 
b/src/test/java/org/apache/skywalking/banyandb/v1/client/metadata/PropertyStoreTest.java
@@ -18,6 +18,7 @@
 
 package org.apache.skywalking.banyandb.v1.client.metadata;
 
+import com.google.common.base.Strings;
 import io.grpc.stub.StreamObserver;
 import org.apache.skywalking.banyandb.property.v1.BanyandbProperty;
 import org.apache.skywalking.banyandb.property.v1.PropertyServiceGrpc;
@@ -32,8 +33,10 @@ import org.junit.Test;
 import java.io.IOException;
 import java.time.ZonedDateTime;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.mockito.AdditionalAnswers.delegatesTo;
 import static org.mockito.Mockito.mock;
@@ -43,6 +46,8 @@ public class PropertyStoreTest extends 
AbstractBanyanDBClientTest {
 
     private Map<String, BanyandbProperty.Property> memory;
 
+    private Set<Long> leasePool;
+
     private final PropertyServiceGrpc.PropertyServiceImplBase 
propertyServiceImpl = mock(PropertyServiceGrpc.PropertyServiceImplBase.class, 
delegatesTo(
             new PropertyServiceGrpc.PropertyServiceImplBase() {
                 @Override
@@ -53,10 +58,16 @@ public class PropertyStoreTest extends 
AbstractBanyanDBClientTest {
                     String key = format(p.getMetadata());
                     BanyandbProperty.Property v = memory.get(key);
                     memory.put(format(p.getMetadata()), p);
+                    BanyandbProperty.ApplyResponse.Builder builder = 
BanyandbProperty.ApplyResponse.newBuilder().setTagsNum(p.getTagsCount());
+                    if (!Strings.isNullOrEmpty(p.getTtl())) {
+                        long leaseId = System.currentTimeMillis();
+                        leasePool.add(leaseId);
+                        builder.setLeaseId(leaseId);
+                    }
                     if (v == null) {
-                        
responseObserver.onNext(BanyandbProperty.ApplyResponse.newBuilder().setCreated(true).setTagsNum(p.getTagsCount()).build());
+                        
responseObserver.onNext(builder.setCreated(true).build());
                     } else {
-                        
responseObserver.onNext(BanyandbProperty.ApplyResponse.newBuilder().setCreated(false).setTagsNum(p.getTagsCount()).build());
+                        
responseObserver.onNext(builder.setCreated(false).build());
                     }
                     responseObserver.onCompleted();
                 }
@@ -80,12 +91,22 @@ public class PropertyStoreTest extends 
AbstractBanyanDBClientTest {
                     
responseObserver.onNext(BanyandbProperty.ListResponse.newBuilder().addAllProperty(memory.values()).build());
                     responseObserver.onCompleted();
                 }
+
+                public void keepAlive(BanyandbProperty.KeepAliveRequest 
request, StreamObserver<BanyandbProperty.KeepAliveResponse> responseObserver) {
+                    if (!leasePool.contains(request.getLeaseId())) {
+                        responseObserver.onError(new RuntimeException("lease 
not found"));
+                    } else {
+                        
responseObserver.onNext(BanyandbProperty.KeepAliveResponse.newBuilder().build());
+                    }
+                    responseObserver.onCompleted();
+                }
             }));
 
     @Before
     public void setUp() throws IOException {
         super.setUp(bindService(propertyServiceImpl));
         this.memory = new HashMap<>();
+        this.leasePool = new HashSet<>();
         this.store = new PropertyStore(this.channel);
     }
 
@@ -138,6 +159,18 @@ public class PropertyStoreTest extends 
AbstractBanyanDBClientTest {
         Assert.assertEquals(0, memory.size());
     }
 
+    @Test
+    public void testPropertyStore_keepAlive() throws BanyanDBException {
+        Property property = Property.create("default", "sw", "ui_template")
+                .addTag(TagAndValue.newStringTag("name", "hello"))
+                .setTtl("30m")
+                .build();
+        PropertyStore.ApplyResult resp = this.store.apply(property);
+        Assert.assertTrue(resp.created());
+        Assert.assertTrue(resp.leaseId() > 0);
+        this.store.keepAlive(resp.leaseId());
+    }
+
     static String format(BanyandbProperty.Metadata metadata) {
         return metadata.getContainer().getGroup() + ":" + 
metadata.getContainer().getName() + "/" + metadata.getId();
     }

Reply via email to