Skip to content

Commit

Permalink
feat: kotlin wrapper for ably-java and ably-android
Browse files Browse the repository at this point in the history
This is the initial version of the Kotlin wrapper for `ably-java` and `ably-android`. The main goal is to provide an extendable public interface for the Ably PubSub SDK (the core SDK for Chat and other products). This wrapper SDK is the first step toward modernizing our libraries. It introduces a set of interfaces that can be modified, for example, to inject agent information or other data when used within new product SDKs.
  • Loading branch information
ttypic committed Feb 10, 2025
1 parent fd12be9 commit 4f23918
Show file tree
Hide file tree
Showing 14 changed files with 780 additions and 1 deletion.
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ firebase-messaging = "22.0.0"
android-test = "1.0.2"
dexmaker = "1.4"
android-retrostreams = "1.7.4"
maven-publish = "0.29.0"
maven-publish = "0.30.0"
lombok = "8.10"
okhttp = "4.12.0"
test-retry = "1.6.0"
kotlin = "2.1.10"

[libraries]
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
Expand Down Expand Up @@ -48,6 +49,7 @@ tests = ["junit","hamcrest-all", "nanohttpd", "nanohttpd-nanolets", "nanohttpd-w
instrumental-android = ["android-test-runner", "android-test-rules", "dexmaker", "dexmaker-dx", "dexmaker-mockito", "android-retrostreams"]

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
android-library = { id = "com.android.library", version.ref = "agp" }
build-config = { id = "com.github.gmazzo.buildconfig", version.ref = "build-config" }
maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" }
Expand Down
10 changes: 10 additions & 0 deletions pubsub-adapter/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
`java-library`
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.maven.publish)
}

dependencies {
compileOnly(project(":java"))
testImplementation(project(":java"))
}
4 changes: 4 additions & 0 deletions pubsub-adapter/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_ARTIFACT_ID=pubsub-adapter
POM_NAME=Internal Ably PubSub adapter
POM_DESCRIPTION=Internal adapter for using Ably PubSub in Kotlin
POM_PACKAGING=jar
74 changes: 74 additions & 0 deletions pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.ably.pubsub

import io.ably.lib.realtime.CompletionListener
import io.ably.lib.types.*

/**
* A class representing a Channel in the Ably API.
*/
interface Channel {

/**
* The channel name.
*/
val name: String

/**
* A [Presence] object.
*
*
* Spec: RTL9
*/
val presence: Presence

/**
* Publish a message on this channel
*
* @param name the event name
* @param data the message payload; see [io.ably.types.Data] for details of supported data types.
*/
fun publish(name: String, data: Any)

/**
* Publish list of messages on this channel. When there are
* multiple messages to be sent, it is more efficient to use this
* method to publish them in a single request, as compared with
* publishing via multiple independent requests.
*
* @param messages list of messages to publish.
*/
fun publish(messages: List<Message>)

/**
* Publish a message on this channel asynchronously
*
* @see [publish]
*/
fun publishAsync(name: String, data: Any, listener: CompletionListener)

/**
* Publish list of messages on this channel asynchronously
*
* @see [publish]
*/
fun publishAsync(messages: List<Message>, listener: CompletionListener)

/**
* Obtain recent history for this channel using the REST API.
* The history provided relqtes to all clients of this application,
* not just this instance.
*
* @param params the request params. See the Ably REST API
* documentation for more details.
* @return Paginated result of Messages for this Channel.
*/
fun history(params: List<Param>): PaginatedResult<Message>

/**
* Asynchronously obtain recent history for this channel using the REST API.
*
* @param params the request params. See the Ably REST API
*/
fun historyAsync(params: List<Param>, callback: Callback<AsyncPaginatedResult<Message>>)

}
48 changes: 48 additions & 0 deletions pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channels.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.ably.pubsub

import io.ably.lib.realtime.ChannelState
import io.ably.lib.types.ChannelOptions

/**
* Represents collection of managed Channel instances
*/
interface Channels<CHANNEL_TYPE> : Iterable<CHANNEL_TYPE> {

/**
* Checks if channel with specified name exists
* <p>
* Spec: RSN2, RTS2
* @param name The channel name.
* @return `true` if it contains the specified [name].
*/
fun exists(name: String): Boolean

/**
* Creates a new [Channel] object, or returns the existing channel object.
* <p>
* Spec: RSN3a, RTS3a
* @param name The channel name.
* @return A [Channel] object.
*/
fun get(name: String): CHANNEL_TYPE

/**
* Creates a new [Channel] object, with the specified [ChannelOptions], or returns the existing channel object.
* <p>
* Spec: RSN3c, RTS3c
* @param name The channel name.
* @param options A [ChannelOptions] object.
* @return A [Channel] object.
*/
fun get(name: String, options: ChannelOptions): CHANNEL_TYPE

/**
* Releases a [Channel] object, deleting it, and enabling it to be garbage collected.
* It also removes any listeners associated with the channel.
* To release a channel, the [ChannelState] must be `INITIALIZED`, `DETACHED`, or `FAILED`.
* <p>
* Spec: RSN4, RTS4
* @param name The channel name.
*/
fun release(name: String)
}
161 changes: 161 additions & 0 deletions pubsub-adapter/src/main/kotlin/com/ably/pubsub/Client.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package com.ably.pubsub

import io.ably.lib.http.*
import io.ably.lib.push.Push
import io.ably.lib.rest.Auth
import io.ably.lib.types.*

/**
* A client that offers a base interface to interact with Ably's API.
*
* This class implements {@link AutoCloseable} so you can use it in
* try-with-resources constructs and have the JDK close it for you.
*/
interface Client : AutoCloseable {

/**
* An [Auth] object.
*
* Spec: RSC5
*/
val auth: Auth

/**
* A [Channels] object.
*
* Spec: RTC3, RTS1
*/
val channels: Channels<out Channel>

/**
* Client options
*/
val options: ClientOptions

/**
* An [Push] object.
*
* Spec: RSH7
*/
val push: Push

/**
* Retrieves the time from the Ably service as milliseconds
* since the Unix epoch. Clients that do not have access
* to a sufficiently well maintained time source and wish
* to issue Ably [Auth.TokenRequest] with
* a more accurate timestamp should use the
* [ClientOptions.queryTime] property instead of this method.
* <p>
* Spec: RSC16
* @return The time as milliseconds since the Unix epoch.
*/
fun time(): Long

/**
* Asynchronously retrieves the time from the Ably service as milliseconds
* since the Unix epoch. Clients that do not have access
* to a sufficiently well maintained time source and wish
* to issue Ably [Auth.TokenRequest] with
* a more accurate timestamp should use the
* [ClientOptions.queryTime] property instead of this method.
*
* Spec: RSC16
*
* @param callback Listener with the time as milliseconds since the Unix epoch.
* This callback is invoked on a background thread
*/
fun timeAsync(callback: Callback<Long>)

/**
* Queries the REST /stats API and retrieves your application's usage statistics.
* @param params query options:
* - start (RSC6b1) - The time from which stats are retrieved, specified as milliseconds since the Unix epoch.
* - end (RSC6b1) - The time until stats are retrieved, specified as milliseconds since the Unix epoch.
* - direction (RSC6b2) - The order for which stats are returned in. Valid values are backwards which orders stats from most recent to oldest,
* or forwards which orders stats from oldest to most recent. The default is backwards.
* - limit (RSC6b3) - An upper limit on the number of stats returned. The default is 100, and the maximum is 1000.
* - unit (RSC6b4) - minute, hour, day or month. Based on the unit selected, the given start or end times are rounded down to the start of the relevant interval depending on the unit granularity of the query.
*
* Spec: RSC6a
*
* @return A [PaginatedResult] object containing an array of [Stats] objects.
* @throws AblyException
*/
fun stats(params: List<Param>): PaginatedResult<Stats>

/**
* Asynchronously queries the REST /stats API and retrieves your application's usage statistics.
* @param params query options:
* - start (RSC6b1) - The time from which stats are retrieved, specified as milliseconds since the Unix epoch.
* - end (RSC6b1) - The time until stats are retrieved, specified as milliseconds since the Unix epoch.
* - direction (RSC6b2) - The order for which stats are returned in. Valid values are backwards which orders stats from most recent to oldest,
* or forwards which orders stats from oldest to most recent. The default is backwards.
* - limit (RSC6b3) - An upper limit on the number of stats returned. The default is 100, and the maximum is 1000.
* - unit (RSC6b4) - minute, hour, day or month. Based on the unit selected, the given start or end times are rounded down to the start of the relevant interval depending on the unit granularity of the query.)
*
* Spec: RSC6a
*
* @param callback Listener which returns a [AsyncPaginatedResult] object containing an array of [Stats] objects.
* This callback is invoked on a background thread
*/
fun statsAsync(params: List<Param>, callback: Callback<AsyncPaginatedResult<Stats>>)

/**
* Makes a REST request to a provided path. This is provided as a convenience
* for developers who wish to use REST API functionality that is either not
* documented or is not yet included in the public API, without having to
* directly handle features such as authentication, paging, fallback hosts,
* MsgPack and JSON support.
*
* Spec: RSC19
*
* @param method The request method to use, such as GET, POST.
* @param path The request path.
* @param params The parameters to include in the URL query of the request.
* The parameters depend on the endpoint being queried.
* See the [REST API reference](https://ably.com/docs/api/rest-api)
* for the available parameters of each endpoint.
* @param body The RequestBody of the request.
* @param headers Additional HTTP headers to include in the request.
* @return An [HttpPaginatedResponse] object returned by the HTTP request, containing an empty or JSON-encodable object.
*/
fun request(
method: String,
path: String,
params: List<Param>,
body: HttpCore.RequestBody,
headers: List<Param>,
)

/**
* Makes a async REST request to a provided path. This is provided as a convenience
* for developers who wish to use REST API functionality that is either not
* documented or is not yet included in the public API, without having to
* directly handle features such as authentication, paging, fallback hosts,
* MsgPack and JSON support.
*
* Spec: RSC19
*
* @param method The request method to use, such as GET, POST.
* @param path The request path.
* @param params The parameters to include in the URL query of the request.
* The parameters depend on the endpoint being queried.
* See the [REST API reference](https://ably.com/docs/api/rest-api)
* for the available parameters of each endpoint.
* @param body The RequestBody of the request.
* @param headers Additional HTTP headers to include in the request.
* @param callback called with the asynchronous result,
* returns an [AsyncHttpPaginatedResponse] object returned by the HTTP request,
* containing an empty or JSON-encodable object.
* This callback is invoked on a background thread
*/
fun requestAsync(
method: String,
path: String,
params: List<Param>,
body: HttpCore.RequestBody,
headers: List<Param>,
callback: AsyncHttpPaginatedResponse.Callback,
)
}
46 changes: 46 additions & 0 deletions pubsub-adapter/src/main/kotlin/com/ably/pubsub/Presence.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.ably.pubsub

import io.ably.lib.types.*

/**
* Enables the retrieval of the current and historic presence set for a channel.
*/
interface Presence {

/**
* Retrieves a [PaginatedResult] object, containing an array of historical [PresenceMessage] objects for the channel.
* If the channel is configured to persist messages,
* then presence messages can be retrieved from history for up to 72 hours in the past.
* If not, presence messages can only be retrieved from history for up to two minutes in the past.
*
* Spec: RSP4a
*
* @param params the request params:
* - start (RSP4b1) - The time from which messages are retrieved, specified as milliseconds since the Unix epoch.
* - end (RSP4b1) - The time until messages are retrieved, specified as milliseconds since the Unix epoch.
* - direction (RSP4b2) - The order for which messages are returned in. Valid values are backwards which orders messages from most recent to oldest,
* or forwards which orders messages from oldest to most recent. The default is backwards.
* - limit (RSP4b3) - An upper limit on the number of messages returned. The default is 100, and the maximum is 1000.
* @return A [PaginatedResult] object containing an array of [PresenceMessage] objects.
*/
fun history(params: List<Param>): PaginatedResult<PresenceMessage>

/**
* Asynchronously retrieves a [PaginatedResult] object, containing an array of historical [PresenceMessage] objects for the channel.
* If the channel is configured to persist messages,
* then presence messages can be retrieved from history for up to 72 hours in the past.
* If not, presence messages can only be retrieved from history for up to two minutes in the past.
*
* Spec: RSP4a
*
* @param params the request params:
* - start (RSP4b1) - The time from which messages are retrieved, specified as milliseconds since the Unix epoch.
* - end (RSP4b1) - The time until messages are retrieved, specified as milliseconds since the Unix epoch.
* - direction (RSP4b2) - The order for which messages are returned in. Valid values are backwards which orders messages from most recent to oldest,
* or forwards which orders messages from oldest to most recent. The default is backwards.
* - limit (RSP4b3) - An upper limit on the number of messages returned. The default is 100, and the maximum is 1000.
* @param callback A Callback returning [AsyncPaginatedResult] object containing an array of [PresenceMessage] objects.
* Note: This callback is invoked on a background thread.
*/
fun historyAsync(params: List<Param>, callback: Callback<AsyncPaginatedResult<PresenceMessage>>)
}
Loading

0 comments on commit 4f23918

Please sign in to comment.