Skip to content

Commit 4128184

Browse files
committed
WIP: liveobjects experemental implementation
1 parent aedfd9b commit 4128184

11 files changed

Lines changed: 111 additions & 6 deletions

File tree

android/src/main/java/io/ably/lib/realtime/Channel.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import io.ably.lib.types.AblyException;
44
import io.ably.lib.types.ChannelOptions;
55
import io.ably.lib.push.PushChannel;
6+
import io.ably.lib.objects.LiveObjectsPlugin;
7+
68

79
public class Channel extends ChannelBase {
810
/**
@@ -12,8 +14,8 @@ public class Channel extends ChannelBase {
1214
*/
1315
public final PushChannel push;
1416

15-
Channel(AblyRealtime ably, String name, ChannelOptions options) throws AblyException {
16-
super(ably, name, options);
17+
Channel(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException {
18+
super(ably, name, options, liveObjectsPlugin);
1719
this.push = ((io.ably.lib.rest.AblyRest) ably).channels.get(name, options).push;
1820
}
1921

java/src/main/java/io/ably/lib/realtime/Channel.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package io.ably.lib.realtime;
22

3+
import io.ably.lib.objects.LiveObjectsPlugin;
34
import io.ably.lib.types.AblyException;
45
import io.ably.lib.types.ChannelOptions;
56

67
public class Channel extends ChannelBase {
7-
Channel(AblyRealtime ably, String name, ChannelOptions options) throws AblyException {
8-
super(ably, name, options);
8+
Channel(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException {
9+
super(ably, name, options, liveObjectsPlugin);
910
}
1011

1112
public interface MessageListener extends ChannelBase.MessageListener {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.ably.lib.objects;
2+
3+
import io.ably.lib.types.Callback;
4+
5+
public interface LiveObjects {
6+
Long getRoot();
7+
void getRootAsync(Callback<Long> callback);
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.ably.lib.objects;
2+
3+
public interface LiveObjectsPlugin {
4+
LiveObjects getInstance(String channelName);
5+
}

lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package io.ably.lib.realtime;
22

3+
import java.lang.reflect.InvocationTargetException;
34
import java.util.ArrayList;
45
import java.util.HashMap;
56
import java.util.List;
67
import java.util.Map;
78

9+
import io.ably.lib.network.HttpEngineFactory;
10+
import io.ably.lib.objects.LiveObjects;
11+
import io.ably.lib.objects.LiveObjectsPlugin;
812
import io.ably.lib.rest.AblyRest;
913
import io.ably.lib.rest.Auth;
1014
import io.ably.lib.transport.ConnectionManager;
@@ -40,6 +44,13 @@ public class AblyRealtime extends AblyRest {
4044
*/
4145
public final Channels channels;
4246

47+
/**
48+
* A nullable reference to the LiveObjects plugin.
49+
* <p>
50+
* This field is initialized only if the LiveObjects plugin is present in the classpath.
51+
*/
52+
private final LiveObjectsPlugin liveObjectsPlugin;
53+
4354
/**
4455
* Constructs a Realtime client object using an Ably API key or token string.
4556
* <p>
@@ -72,6 +83,8 @@ public AblyRealtime(ClientOptions options) throws AblyException {
7283
}
7384
}
7485

86+
liveObjectsPlugin = tryInitializeLiveObjectsPlugin();
87+
7588
if(options.autoConnect) connection.connect();
7689
}
7790

@@ -168,6 +181,16 @@ public interface Channels extends ReadOnlyMap<String, Channel> {
168181
void release(String channelName);
169182
}
170183

184+
private LiveObjectsPlugin tryInitializeLiveObjectsPlugin() {
185+
try {
186+
Class<?> liveObjectsImplementation = Class.forName("io.ably.lib.objects.DefaultLiveObjectsPlugin");
187+
return (LiveObjectsPlugin) liveObjectsImplementation.getDeclaredConstructor().newInstance();
188+
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException |
189+
InvocationTargetException e) {
190+
return null;
191+
}
192+
}
193+
171194
private class InternalChannels extends InternalMap<String, Channel> implements Channels, ConnectionManager.Channels {
172195
/**
173196
* Get the named channel; if it does not already exist,
@@ -187,7 +210,7 @@ public Channel get(final String channelName, final ChannelOptions channelOptions
187210
// We're not using computeIfAbsent because that requires Java 1.8.
188211
// Hence there's the slight inefficiency of creating newChannel when it may not be
189212
// needed because there is an existingChannel.
190-
final Channel newChannel = new Channel(AblyRealtime.this, channelName, channelOptions);
213+
final Channel newChannel = new Channel(AblyRealtime.this, channelName, channelOptions, liveObjectsPlugin);
191214
final Channel existingChannel = map.putIfAbsent(channelName, newChannel);
192215

193216
if (existingChannel != null) {

lib/src/main/java/io/ably/lib/realtime/ChannelBase.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import io.ably.lib.http.Http;
1414
import io.ably.lib.http.HttpCore;
1515
import io.ably.lib.http.HttpUtils;
16+
import io.ably.lib.objects.LiveObjects;
17+
import io.ably.lib.objects.LiveObjectsPlugin;
1618
import io.ably.lib.transport.ConnectionManager;
1719
import io.ably.lib.transport.ConnectionManager.QueuedMessage;
1820
import io.ably.lib.transport.Defaults;
@@ -91,6 +93,23 @@ public abstract class ChannelBase extends EventEmitter<ChannelEvent, ChannelStat
9193
*/
9294
private boolean released = false;
9395

96+
private final LiveObjectsPlugin liveObjectsPlugin;
97+
private LiveObjects objects;
98+
99+
public LiveObjects getObjects() throws AblyException {
100+
if (liveObjectsPlugin == null) {
101+
throw AblyException.fromErrorInfo(
102+
new ErrorInfo("LiveObjects plugin hasn't been installed, add runtimeOnly('io.ably:live-objects:<ably-version>') to your dependency tree", 400, 40000)
103+
);
104+
}
105+
106+
if (objects == null) {
107+
objects = liveObjectsPlugin.getInstance(name);
108+
}
109+
110+
return objects;
111+
}
112+
94113
/***
95114
* internal
96115
*
@@ -1285,7 +1304,7 @@ else if(stateChange.current.equals(failureState)) {
12851304
}
12861305
}
12871306

1288-
ChannelBase(AblyRealtime ably, String name, ChannelOptions options) throws AblyException {
1307+
ChannelBase(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException {
12891308
Log.v(TAG, "RealtimeChannel(); channel = " + name);
12901309
this.ably = ably;
12911310
this.name = name;
@@ -1295,6 +1314,7 @@ else if(stateChange.current.equals(failureState)) {
12951314
this.attachResume = false;
12961315
state = ChannelState.initialized;
12971316
this.decodingContext = new DecodingContext();
1317+
this.liveObjectsPlugin = liveObjectsPlugin;
12981318
}
12991319

13001320
void onChannelMessage(ProtocolMessage msg) {

live-objects/build.gradle.kts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
plugins {
2+
`java-library`
3+
alias(libs.plugins.kotlin.jvm)
4+
}
5+
6+
repositories {
7+
mavenCentral()
8+
}
9+
10+
dependencies {
11+
implementation(project(":java"))
12+
testImplementation(kotlin("test"))
13+
}
14+
15+
tasks.test {
16+
useJUnitPlatform()
17+
}
18+
19+
kotlin {
20+
explicitApi()
21+
}

live-objects/gradle.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
POM_ARTIFACT_ID=live-objects
2+
POM_NAME=Live Objects plugin for Ably Pub/Sub SDK
3+
POM_DESCRIPTION=Live Objects plugin for Ably Pub/Sub SDK
4+
POM_PACKAGING=jar
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.ably.lib.objects
2+
3+
import io.ably.lib.types.Callback
4+
5+
internal class DefaultLiveObjects(private val channelName: String): LiveObjects {
6+
7+
override fun getRoot(): Long = channelName.length.toLong()
8+
9+
override fun getRootAsync(callback: Callback<Long>) {
10+
callback.onSuccess(channelName.length.toLong())
11+
}
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.ably.lib.objects
2+
3+
public class DefaultLiveObjectsPlugin(): LiveObjectsPlugin {
4+
override fun greetings(): String = "Hello from Live Objects module"
5+
6+
override fun getInstance(channelName: String): LiveObjects = DefaultLiveObjects(channelName)
7+
8+
}

0 commit comments

Comments
 (0)