Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve behavior for realtime channel creation and improve docs #831

Merged
merged 6 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ sealed interface Realtime : MainPlugin<Realtime.Config>, CustomSerializationPlug
val status: StateFlow<Status>

/**
* A map of all active the subscriptions
* A list of all active the subscriptions
*/
val subscriptions: Map<String, RealtimeChannel>

Expand Down Expand Up @@ -103,6 +103,17 @@ sealed interface Realtime : MainPlugin<Realtime.Config>, CustomSerializationPlug
*/
suspend fun setAuth(token: String? = null)

/**
* Creates a new [RealtimeChannel] and adds it to the [subscriptions]
*
* - This method does not subscribe to the channel. You have to call [RealtimeChannel.subscribe] to do so.
* - If the channel already exists, it will be returned
*
* @param channelId The id of the channel
* @param builder The builder for the channel
*/
fun channel(channelId: String, builder: RealtimeChannelBuilder): RealtimeChannel

/**
* @property websocketConfig Custom configuration for the Ktor Websocket Client. This only applies if [Realtime.Config.websocketFactory] is null.
* @property secure Whether to use wss or ws. Defaults to [SupabaseClient.useHTTPS] when null
Expand Down Expand Up @@ -187,11 +198,15 @@ sealed interface Realtime : MainPlugin<Realtime.Config>, CustomSerializationPlug
}

/**
* Creates a new [RealtimeChannel]
* Creates a new [RealtimeChannel] and adds it to the [Realtime.subscriptions]
*
* - This method does not subscribe to the channel. You have to call [RealtimeChannel.subscribe] to do so.
* - If the channel already exists, it will be returned
*
* @param channelId The id of the channel
* @param builder The builder for the channel
*/
inline fun Realtime.channel(channelId: String, builder: RealtimeChannelBuilder.() -> Unit = {}): RealtimeChannel {
return RealtimeChannelBuilder("realtime:$channelId", this as RealtimeImpl).apply(builder).build()
}
inline fun Realtime.channel(channelId: String, builder: RealtimeChannelBuilder.() -> Unit = {}): RealtimeChannel = channel(channelId, RealtimeChannelBuilder("realtime:$channelId", this as RealtimeImpl).apply(builder))

/**
* Supabase Realtime is a way to listen to changes in the PostgreSQL database via websockets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ import kotlin.io.encoding.ExperimentalEncodingApi
_status.value = Realtime.Status.DISCONNECTED
}

override fun channel(channelId: String, builder: RealtimeChannelBuilder): RealtimeChannel {
if(subscriptions.containsKey(channelId)) return subscriptions[channelId]!!
val channel = builder.build()
_subscriptions[channelId] = channel
return channel
}

private suspend fun onMessage(message: RealtimeMessage) {
Realtime.logger.d { "Received message $message" }
val channel = subscriptions[message.topic] as? RealtimeChannelImpl
Expand Down
17 changes: 17 additions & 0 deletions Realtime/src/commonTest/kotlin/RealtimeTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io.github.jan.supabase.realtime.Realtime
import io.github.jan.supabase.realtime.RealtimeImpl
import io.github.jan.supabase.realtime.RealtimeMessage
import io.github.jan.supabase.realtime.channel
import io.github.jan.supabase.realtime.realtime
import io.ktor.util.encodeBase64
import kotlinx.coroutines.test.runTest
Expand Down Expand Up @@ -31,6 +32,22 @@ class RealtimeTest {
}
}

@Test
fun testExistingChannelShouldBeReturned() {
runTest {
createTestClient(
wsHandler = { _, _ ->
//Does not matter for this test
},
supabaseHandler = {
val channel = it.realtime.channel("channelId")
val channel2 = it.realtime.channel("channelId")
assertEquals(channel, channel2)
}
)
}
}

@Test
fun testSendingRealtimeMessages() {
val expectedMessage = RealtimeMessage(
Expand Down
Loading