diff --git a/lib/src/main/java/io/ably/lib/objects/ObjectsPlugin.java b/lib/src/main/java/io/ably/lib/objects/ObjectsPlugin.java index ef30ab7f8..be149843b 100644 --- a/lib/src/main/java/io/ably/lib/objects/ObjectsPlugin.java +++ b/lib/src/main/java/io/ably/lib/objects/ObjectsPlugin.java @@ -38,7 +38,7 @@ public interface ObjectsPlugin { * * @param channelName the name of the channel whose state has changed. * @param state the new state of the channel. - * @param hasObjects flag indicates whether the channel has any associated live objects. + * @param hasObjects flag indicates whether the channel has any associated objects. */ void handleStateChange(@NotNull String channelName, @NotNull ChannelState state, boolean hasObjects); diff --git a/lib/src/main/java/io/ably/lib/objects/RealtimeObjects.java b/lib/src/main/java/io/ably/lib/objects/RealtimeObjects.java index 950b41bf6..6e111b304 100644 --- a/lib/src/main/java/io/ably/lib/objects/RealtimeObjects.java +++ b/lib/src/main/java/io/ably/lib/objects/RealtimeObjects.java @@ -13,7 +13,7 @@ /** * The RealtimeObjects interface provides methods to interact with live data objects, * such as maps and counters, in a real-time environment. It supports both synchronous - * and asynchronous operations for retrieving and creating live objects. + * and asynchronous operations for retrieving and creating objects. * *
Implementations of this interface must be thread-safe as they may be accessed * from multiple threads concurrently. diff --git a/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateChange.java b/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateChange.java index 7b3a7e1e3..180645f3c 100644 --- a/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateChange.java +++ b/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateChange.java @@ -6,7 +6,7 @@ public interface ObjectsStateChange { /** - * Subscribes to a specific Live Objects synchronization state event. + * Subscribes to a specific Objects synchronization state event. * *
This method registers the provided listener to be notified when the specified * synchronization state event occurs. The returned subscription can be used to @@ -40,7 +40,7 @@ public interface ObjectsStateChange { void offAll(); /** - * Interface for receiving notifications about Live Objects synchronization state changes. + * Interface for receiving notifications about Objects synchronization state changes. *
* Implement this interface and register it with an ObjectsStateEmitter to be notified * when synchronization state transitions occur. diff --git a/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateEvent.java b/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateEvent.java index 4fa01a173..1aa27203a 100644 --- a/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateEvent.java +++ b/lib/src/main/java/io/ably/lib/objects/state/ObjectsStateEvent.java @@ -1,7 +1,7 @@ package io.ably.lib.objects.state; /** - * Represents the synchronization state of Ably Live Objects. + * Represents the synchronization state of Ably Objects. *
* This enum is used to notify listeners about state changes in the synchronization process. * Clients can register an {@link ObjectsStateChange.Listener} to receive these events. diff --git a/lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleChange.java b/lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleChange.java new file mode 100644 index 000000000..c8d0f5745 --- /dev/null +++ b/lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleChange.java @@ -0,0 +1,69 @@ +package io.ably.lib.objects.type; + +import io.ably.lib.objects.ObjectsSubscription; +import org.jetbrains.annotations.NonBlocking; +import org.jetbrains.annotations.NotNull; + +/** + * Interface for managing subscriptions to Object lifecycle events. + *
+ * This interface provides methods to subscribe to and manage notifications about significant lifecycle + * changes that occur to Object, such as deletion. More events can be added in the future. + * Multiple listeners can be registered independently, and each can be managed separately. + *
+ * Lifecycle events are different from data update events - they represent changes + * to the object's existence state rather than changes to the object's data content. + * + * @see ObjectLifecycleEvent for the available lifecycle events + */ +public interface ObjectLifecycleChange { + /** + * Subscribes to a specific Object lifecycle event. + * + *
This method registers the provided listener to be notified when the specified + * lifecycle event occurs. The returned subscription can be used to + * unsubscribe later when the notifications are no longer needed. + * + * @param event the lifecycle event to subscribe to + * @param listener the listener that will be called when the event occurs + * @return a subscription object that can be used to unsubscribe from the event + */ + @NonBlocking + ObjectsSubscription on(@NotNull ObjectLifecycleEvent event, @NotNull ObjectLifecycleChange.Listener listener); + + /** + * Unsubscribes the specified listener from all lifecycle events. + * + *
After calling this method, the provided listener will no longer receive + * any lifecycle event notifications. + * + * @param listener the listener to unregister from all events + */ + @NonBlocking + void off(@NotNull ObjectLifecycleChange.Listener listener); + + /** + * Unsubscribes all listeners from all lifecycle events. + * + *
After calling this method, no listeners will receive any lifecycle + * event notifications until new listeners are registered. + */ + @NonBlocking + void offAll(); + + /** + * Interface for receiving notifications about Object lifecycle changes. + *
+ * Implement this interface and register it with an ObjectLifecycleChange provider + * to be notified when lifecycle events occur, such as object creation or deletion. + */ + @FunctionalInterface + interface Listener { + /** + * Called when a lifecycle event occurs. + * + * @param lifecycleEvent The lifecycle event that occurred + */ + void onLifecycleEvent(@NotNull ObjectLifecycleEvent lifecycleEvent); + } +} diff --git a/lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleEvent.java b/lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleEvent.java new file mode 100644 index 000000000..7a2d1aa7d --- /dev/null +++ b/lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleEvent.java @@ -0,0 +1,16 @@ +package io.ably.lib.objects.type; + +/** + * Represents lifecycle events for an Ably Object. + *
+ * This enum notifies listeners about significant lifecycle changes that occur to an Object during its lifetime.
+ * Clients can register a {@link ObjectLifecycleChange.Listener} to receive these events.
+ */
+public enum ObjectLifecycleEvent {
+ /**
+ * Indicates that an Object has been deleted (tombstoned).
+ * Emitted once when the object is tombstoned server-side (i.e., deleted and no longer addressable).
+ * Not re-emitted during client-side garbage collection of tombstones.
+ */
+ DELETED
+}
diff --git a/lib/src/main/java/io/ably/lib/objects/type/ObjectUpdate.java b/lib/src/main/java/io/ably/lib/objects/type/ObjectUpdate.java
index 6df47cf99..8ee1e1578 100644
--- a/lib/src/main/java/io/ably/lib/objects/type/ObjectUpdate.java
+++ b/lib/src/main/java/io/ably/lib/objects/type/ObjectUpdate.java
@@ -5,7 +5,7 @@
/**
* Abstract base class for all LiveMap/LiveCounter update notifications.
* Provides common structure for updates that occur on LiveMap and LiveCounter objects.
- * Contains the update data that describes what changed in the live object.
+ * Contains the update data that describes what changed in the object.
* Spec: RTLO4b4
*/
public abstract class ObjectUpdate {
diff --git a/lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java b/lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java
index c23ccc91b..958cf05b1 100644
--- a/lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java
+++ b/lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java
@@ -1,6 +1,7 @@
package io.ably.lib.objects.type.counter;
import io.ably.lib.objects.ObjectsCallback;
+import io.ably.lib.objects.type.ObjectLifecycleChange;
import org.jetbrains.annotations.Blocking;
import org.jetbrains.annotations.NonBlocking;
import org.jetbrains.annotations.NotNull;
@@ -11,7 +12,7 @@
* It allows incrementing, decrementing, and retrieving the current value of the counter,
* both synchronously and asynchronously.
*/
-public interface LiveCounter extends LiveCounterChange {
+public interface LiveCounter extends LiveCounterChange, ObjectLifecycleChange {
/**
* Increments the value of the counter by the specified amount.
diff --git a/lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java b/lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
index 46c336360..f180fe168 100644
--- a/lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
+++ b/lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
@@ -1,6 +1,7 @@
package io.ably.lib.objects.type.map;
import io.ably.lib.objects.ObjectsCallback;
+import io.ably.lib.objects.type.ObjectLifecycleChange;
import org.jetbrains.annotations.Blocking;
import org.jetbrains.annotations.NonBlocking;
import org.jetbrains.annotations.Contract;
@@ -14,7 +15,7 @@
* The LiveMap interface provides methods to interact with a live, real-time map structure.
* It supports both synchronous and asynchronous operations for managing key-value pairs.
*/
-public interface LiveMap extends LiveMapChange {
+public interface LiveMap extends LiveMapChange, ObjectLifecycleChange {
/**
* Retrieves the value associated with the specified key.
diff --git a/live-objects/src/main/kotlin/io/ably/lib/objects/DefaultRealtimeObjects.kt b/live-objects/src/main/kotlin/io/ably/lib/objects/DefaultRealtimeObjects.kt
index 0b00a1680..00401c50e 100644
--- a/live-objects/src/main/kotlin/io/ably/lib/objects/DefaultRealtimeObjects.kt
+++ b/live-objects/src/main/kotlin/io/ably/lib/objects/DefaultRealtimeObjects.kt
@@ -20,12 +20,12 @@ import java.util.concurrent.CancellationException
/**
* Default implementation of RealtimeObjects interface.
- * Provides the core functionality for managing live objects on a channel.
+ * Provides the core functionality for managing objects on a channel.
*/
internal class DefaultRealtimeObjects(internal val channelName: String, internal val adapter: ObjectsAdapter): RealtimeObjects {
private val tag = "DefaultRealtimeObjects"
/**
- * @spec RTO3 - Objects pool storing all live objects by object ID
+ * @spec RTO3 - Objects pool storing all objects by object ID
*/
internal val objectsPool = ObjectsPool(this)
diff --git a/live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsPool.kt b/live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsPool.kt
index a874d6dd6..28ee839e0 100644
--- a/live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsPool.kt
+++ b/live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsPool.kt
@@ -28,9 +28,9 @@ internal object ObjectsPoolDefaults {
internal const val ROOT_OBJECT_ID = "root"
/**
- * ObjectsPool manages a pool of live objects for a channel.
+ * ObjectsPool manages a pool of objects for a channel.
*
- * @spec RTO3 - Maintains an objects pool for all live objects on the channel
+ * @spec RTO3 - Maintains an objects pool for all objects on the channel
*/
internal class ObjectsPool(
private val realtimeObjects: DefaultRealtimeObjects
@@ -39,7 +39,7 @@ internal class ObjectsPool(
/**
* ConcurrentHashMap for thread-safe access from public APIs in LiveMap and LiveCounter.
- * @spec RTO3a - Pool storing all live objects by object ID
+ * @spec RTO3a - Pool storing all ably objects by object ID
*/
private val pool = ConcurrentHashMap