Skip to content

Commit 3de1532

Browse files
committed
[ECO-5076] Implemented code for getRoot method
1 parent e808d38 commit 3de1532

6 files changed

Lines changed: 97 additions & 20 deletions

File tree

lib/src/main/java/io/ably/lib/objects/Adapter.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package io.ably.lib.objects;
22

33
import io.ably.lib.realtime.AblyRealtime;
4+
import io.ably.lib.realtime.ChannelState;
45
import io.ably.lib.realtime.CompletionListener;
56
import io.ably.lib.types.AblyException;
7+
import io.ably.lib.types.ChannelMode;
68
import io.ably.lib.types.ProtocolMessage;
79
import io.ably.lib.util.Log;
810
import org.jetbrains.annotations.NotNull;
@@ -34,4 +36,22 @@ public void send(@NotNull ProtocolMessage msg, @NotNull CompletionListener liste
3436
public int maxMessageSizeLimit() {
3537
return ably.connection.connectionManager.maxMessageSize;
3638
}
39+
40+
@Override
41+
public ChannelMode[] getChannelMode(@NotNull String channelName) {
42+
if (ably.channels.containsKey(channelName)) {
43+
return ably.channels.get(channelName).getModes();
44+
}
45+
Log.e(TAG, "getChannelMode(): channel not found: " + channelName);
46+
return null;
47+
}
48+
49+
@Override
50+
public ChannelState getChannelState(@NotNull String channelName) {
51+
if (ably.channels.containsKey(channelName)) {
52+
return ably.channels.get(channelName).state;
53+
}
54+
Log.e(TAG, "getChannelState(): channel not found: " + channelName);
55+
return null;
56+
}
3757
}

lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package io.ably.lib.objects;
22

3+
import io.ably.lib.realtime.ChannelState;
34
import io.ably.lib.realtime.CompletionListener;
45
import io.ably.lib.types.AblyException;
6+
import io.ably.lib.types.ChannelMode;
57
import io.ably.lib.types.ProtocolMessage;
68
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
710

811
public interface LiveObjectsAdapter {
912
/**
@@ -31,5 +34,23 @@ public interface LiveObjectsAdapter {
3134
* @return the maximum message size limit in bytes.
3235
*/
3336
int maxMessageSizeLimit();
37+
38+
/**
39+
* Retrieves the channel modes for a specific channel.
40+
* This method returns the modes that are set for the specified channel.
41+
*
42+
* @param channelName the name of the channel for which to retrieve the modes
43+
* @return the array of channel modes for the specified channel, or null if the channel is not found
44+
*/
45+
@Nullable ChannelMode[] getChannelMode(@NotNull String channelName);
46+
47+
/**
48+
* Retrieves the current state of a specific channel.
49+
* This method returns the state of the specified channel, which indicates its connection status.
50+
*
51+
* @param channelName the name of the channel for which to retrieve the state
52+
* @return the current state of the specified channel, or null if the channel is not found
53+
*/
54+
@Nullable ChannelState getChannelState(@NotNull String channelName);
3455
}
3556

live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ internal class DefaultLiveObjects(private val channelName: String, internal val
4141
private val sequentialScope =
4242
CoroutineScope(Dispatchers.Default.limitedParallelism(1) + CoroutineName(channelName) + SupervisorJob())
4343

44+
/**
45+
* Coroutine scope for handling callbacks asynchronously.
46+
*/
47+
private val callbackScope = CoroutineScope(Dispatchers.Default + CoroutineName("LiveObjectsCallback-$channelName"))
48+
4449
/**
4550
* Event bus for handling incoming object messages sequentially.
4651
*/
@@ -51,11 +56,20 @@ internal class DefaultLiveObjects(private val channelName: String, internal val
5156
incomingObjectsHandler = initializeHandlerForIncomingObjectMessages()
5257
}
5358

54-
/**
55-
* @spec RTO1 - Returns the root LiveMap object with proper validation and sync waiting
56-
*/
59+
private suspend fun getRootAsync(): LiveMap {
60+
return withContext(sequentialScope.coroutineContext) {
61+
adapter.throwIfInvalidAccessApiConfiguration(channelName)
62+
// TODO - wait for state in synced state
63+
objectsPool.get(ROOT_OBJECT_ID) as LiveMap
64+
}
65+
}
66+
5767
override fun getRoot(): LiveMap {
58-
TODO("Not yet implemented")
68+
return runBlocking { getRootAsync() }
69+
}
70+
71+
override fun getRootAsync(callback: Callback<LiveMap>) {
72+
callbackScope.with(callback) { getRootAsync() }
5973
}
6074

6175
override fun createMap(liveMap: LiveMap): LiveMap {
@@ -70,10 +84,6 @@ internal class DefaultLiveObjects(private val channelName: String, internal val
7084
TODO("Not yet implemented")
7185
}
7286

73-
override fun getRootAsync(callback: Callback<LiveMap>) {
74-
TODO("Not yet implemented")
75-
}
76-
7787
override fun createMapAsync(liveMap: LiveMap, callback: Callback<LiveMap>) {
7888
TODO("Not yet implemented")
7989
}

live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.ably.lib.objects
22

3+
import io.ably.lib.realtime.ChannelState
34
import io.ably.lib.realtime.CompletionListener
5+
import io.ably.lib.types.ChannelMode
46
import io.ably.lib.types.ErrorInfo
57
import io.ably.lib.types.ProtocolMessage
68
import kotlinx.coroutines.suspendCancellableCoroutine
@@ -39,6 +41,15 @@ internal fun LiveObjectsAdapter.setChannelSerial(channelName: String, protocolMe
3941
setChannelSerial(channelName, channelSerial)
4042
}
4143

44+
internal fun LiveObjectsAdapter.throwIfInvalidAccessApiConfiguration(channelName: String): String? {
45+
}
46+
47+
internal fun LiveObjectsAdapter.throwIfMissingChannelMode(channelName: String, channelMode: ChannelMode): String? {
48+
}
49+
50+
internal fun LiveObjectsAdapter.throwIfInChannelState(channelName: String, channelStates: Array<ChannelState>): String? {
51+
}
52+
4253
internal enum class ProtocolMessageFormat(private val value: String) {
4354
Msgpack("msgpack"),
4455
Json("json");

live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsPool.kt

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,12 @@ internal class ObjectsPool(
4848
private var gcJob: Job // Job for the garbage collection coroutine
4949

5050
init {
51-
// Initialize pool with root object
52-
createInitialPool()
51+
// RTO3b - Initialize pool with root object
52+
pool[ROOT_OBJECT_ID] = DefaultLiveMap.zeroValue(ROOT_OBJECT_ID, adapter, this)
5353
// Start garbage collection coroutine
5454
gcJob = startGCJob()
5555
}
5656

57-
/**
58-
* Creates the initial pool with root object.
59-
*
60-
* @spec RTO3b - Creates root LiveMap object
61-
*/
62-
private fun createInitialPool() {
63-
val root = DefaultLiveMap.zeroValue(ROOT_OBJECT_ID, adapter, this)
64-
pool[ROOT_OBJECT_ID] = root
65-
}
66-
6757
/**
6858
* Gets a live object from the pool by object ID.
6959
*/

live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.ably.lib.objects
22

33
import io.ably.lib.types.AblyException
4+
import io.ably.lib.types.Callback
45
import io.ably.lib.types.ErrorInfo
6+
import kotlinx.coroutines.*
57

68
internal fun ablyException(
79
errorMessage: String,
@@ -44,3 +46,26 @@ internal fun objectError(errorMessage: String, cause: Throwable? = null): AblyEx
4446
*/
4547
internal val String.byteSize: Int
4648
get() = this.toByteArray(Charsets.UTF_8).size
49+
50+
/**
51+
* Executes a suspend function within a coroutine and handles the result via a callback.
52+
*
53+
* This utility bridges between coroutine-based implementation code and callback-based APIs.
54+
* It launches a coroutine in the current scope to execute the provided suspend block,
55+
* then routes the result or any error to the appropriate callback method.
56+
*
57+
* @param T The type of result expected from the operation
58+
* @param callback The callback to invoke with the operation result or error
59+
* @param block The suspend function to execute that returns a value of type T
60+
*/
61+
internal fun <T> CoroutineScope.with(callback: Callback<T>, block: suspend () -> T) {
62+
launch {
63+
try {
64+
val result = block()
65+
callback.onSuccess(result)
66+
} catch (throwable: Throwable) {
67+
val exception = throwable as? AblyException
68+
callback.onError(exception?.errorInfo)
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)