-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from mnbjhu/live_queries
Live queries
- Loading branch information
Showing
51 changed files
with
579 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/commonMain/kotlin/uk/gibby/driver/annotation/SurrealDbNightlyOnlyApi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package uk.gibby.driver.annotation | ||
|
||
@RequiresOptIn(message = "This function is only available while using nightly builds of SurrealDB. See https://surrealdb.com/docs/installation/nightly.") | ||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) | ||
@Retention(AnnotationRetention.BINARY) | ||
annotation class SurrealDbNightlyOnlyApi |
56 changes: 56 additions & 0 deletions
56
src/commonMain/kotlin/uk/gibby/driver/api/LiveQueryFlow.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package uk.gibby.driver.api | ||
|
||
import io.ktor.utils.io.core.* | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.map | ||
import uk.gibby.driver.Surreal | ||
import uk.gibby.driver.annotation.SurrealDbNightlyOnlyApi | ||
import uk.gibby.driver.model.rpc.LiveQueryAction | ||
|
||
/** | ||
* Live query flow | ||
* | ||
* This class is a wrapper around a flow of [LiveQueryAction]s making it [Closeable]. | ||
* | ||
* @param T The type of the records | ||
* @property flow The flow of [LiveQueryAction]s | ||
* @property id The id of the live query | ||
* @property connection The connection to the database | ||
* @constructor Creates a new live query flow | ||
*/ | ||
@SurrealDbNightlyOnlyApi | ||
class LiveQueryFlow<T>( | ||
private val flow: Flow<LiveQueryAction<T>>, | ||
val id: String, | ||
private val connection: Surreal | ||
): Flow<LiveQueryAction<T>> by flow, Closeable { | ||
|
||
/** | ||
* Close | ||
* | ||
* This method will unsubscribe from the live query and trigger the kill RPC request. | ||
*/ | ||
|
||
override fun close() { | ||
connection.unsubscribe(id) | ||
connection.triggerKill(id) | ||
} | ||
|
||
/** | ||
* Map | ||
* | ||
* Used to map the records of the live query flow form [T] to [R]. | ||
* | ||
* @param R The type of the records in the new flow | ||
* @param transform The transform function from [T] to [R] | ||
* @receiver The live query flow to map | ||
* @return A new live query flow of [R]s | ||
*/ | ||
fun <R>map(transform: (LiveQueryAction<T>) -> LiveQueryAction<R>): LiveQueryFlow<R> { | ||
return LiveQueryFlow( | ||
flow = flow.map { transform(it) }, | ||
id = id, | ||
connection = connection | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package uk.gibby.driver.api | ||
|
||
import kotlinx.serialization.json.JsonElement | ||
import uk.gibby.driver.Surreal | ||
import uk.gibby.driver.annotation.SurrealDbNightlyOnlyApi | ||
import uk.gibby.driver.rpc.live | ||
import uk.gibby.driver.model.rpc.asType | ||
import kotlin.jvm.JvmName | ||
|
||
/** | ||
* Observe live query as json | ||
* | ||
* Creates a [LiveQueryFlow] for the given table. | ||
* | ||
* @param table Name of the table to 'LIVE SELECT' from | ||
* @return A [LiveQueryFlow] of [JsonElement]s | ||
*/ | ||
@JvmName("observeJson") | ||
@SurrealDbNightlyOnlyApi | ||
suspend fun Surreal.observeLiveQueryAsJson(table: String): LiveQueryFlow<JsonElement> { | ||
val liveQueryId = live(table) | ||
return LiveQueryFlow( | ||
flow = subscribeAsJson(liveQueryId), | ||
id = liveQueryId, | ||
connection = this | ||
) | ||
} | ||
|
||
|
||
/** | ||
* Observe live query | ||
* | ||
* Creates a [LiveQueryFlow] for the given table. | ||
* | ||
* @param T The type of the records | ||
* @param table Name of the table to 'LIVE SELECT' from | ||
* @return A [LiveQueryFlow] of [T]s | ||
*/ | ||
@SurrealDbNightlyOnlyApi | ||
suspend inline fun <reified T>Surreal.observeLiveQuery(table: String): LiveQueryFlow<T> { | ||
val jsonFlow = observeLiveQueryAsJson(table) | ||
return jsonFlow.map { it.asType<T>() } | ||
} |
5 changes: 5 additions & 0 deletions
5
src/commonMain/kotlin/uk/gibby/driver/exception/LiveQueryKilledException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package uk.gibby.driver.exception | ||
|
||
import kotlinx.coroutines.CancellationException | ||
|
||
object LiveQueryKilledException: CancellationException("Live query has been killed") |
3 changes: 3 additions & 0 deletions
3
src/commonMain/kotlin/uk/gibby/driver/exception/QueryException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package uk.gibby.driver.exception | ||
|
||
data class QueryException(val detail: String): Exception("SurrealDB responded with an error: '$detail'") |
2 changes: 1 addition & 1 deletion
2
...kotlin/uk/gibby/driver/rpc/model/Patch.kt → ...kotlin/uk/gibby/driver/model/JsonPatch.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...lin/uk/gibby/driver/rpc/model/RootAuth.kt → .../kotlin/uk/gibby/driver/model/RootAuth.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...kotlin/uk/gibby/driver/rpc/model/Thing.kt → ...ain/kotlin/uk/gibby/driver/model/Thing.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
.../kotlin/uk/gibby/driver/rpc/model/Bind.kt → ...otlin/uk/gibby/driver/model/query/Bind.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...k/gibby/driver/rpc/model/QueryResponse.kt → ...gibby/driver/model/query/QueryResponse.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
src/commonMain/kotlin/uk/gibby/driver/model/rpc/LiveQueryAction.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package uk.gibby.driver.model.rpc | ||
|
||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.json.JsonElement | ||
import kotlinx.serialization.json.decodeFromJsonElement | ||
import uk.gibby.driver.model.rpc.LiveQueryAction.* | ||
import uk.gibby.driver.surrealJson | ||
|
||
|
||
/** | ||
* LiveQueryAction | ||
* | ||
* A live query action. Can be a [Create], [Update] or [Delete]. | ||
* Holds the id of the record and the result if relevant. | ||
* | ||
* @param T The type of the result | ||
*/ | ||
@Serializable(with = LiveQueryActionSerializer::class) | ||
sealed class LiveQueryAction<out T> { | ||
abstract val id: String | ||
data class Create<T>(override val id: String, val result: T): LiveQueryAction<T>() | ||
data class Update<T>(override val id: String, val result: T): LiveQueryAction<T>() | ||
data class Delete(override val id: String, val deletedId: String): LiveQueryAction<Nothing>() | ||
} | ||
|
||
|
||
/** | ||
* As type | ||
* | ||
* Maps the live query to type [T] using [decodeFromJsonElement] | ||
* | ||
* @param T The new type | ||
* @return The new live query action | ||
*/ | ||
inline fun <reified T> LiveQueryAction<JsonElement>.asType(): LiveQueryAction<T> { | ||
return when(this) { | ||
is Delete -> this | ||
is Create -> Create(id, surrealJson.decodeFromJsonElement(result)) | ||
is Update -> Update(id, surrealJson.decodeFromJsonElement(result)) | ||
} | ||
} | ||
|
49 changes: 49 additions & 0 deletions
49
src/commonMain/kotlin/uk/gibby/driver/model/rpc/LiveQueryActionSerializer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package uk.gibby.driver.model.rpc | ||
|
||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.SerializationException | ||
import kotlinx.serialization.builtins.serializer | ||
import kotlinx.serialization.descriptors.SerialDescriptor | ||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor | ||
import kotlinx.serialization.encoding.CompositeDecoder | ||
import kotlinx.serialization.encoding.Decoder | ||
import kotlinx.serialization.encoding.Encoder | ||
import uk.gibby.driver.model.Thing | ||
import uk.gibby.driver.model.ThingSerializer | ||
|
||
class LiveQueryActionSerializer<T: Any>(private val resultSerializer: KSerializer<T>): KSerializer<LiveQueryAction<T>> { | ||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("LiveQueryAction") { | ||
element("action", String.serializer().descriptor) | ||
element("id", String.serializer().descriptor) | ||
element("result", resultSerializer.descriptor) | ||
} | ||
|
||
override fun deserialize(decoder: Decoder): LiveQueryAction<T> { | ||
val input = decoder.beginStructure(descriptor) | ||
var action: String? = null | ||
var id: String? = null | ||
var result: Thing<T>? = null | ||
loop@ while (true) { | ||
when (val i = input.decodeElementIndex(descriptor)) { | ||
CompositeDecoder.DECODE_DONE -> break@loop | ||
0 -> action = input.decodeStringElement(descriptor, i) | ||
1 -> id = input.decodeStringElement(descriptor, i) | ||
2 -> result = input.decodeSerializableElement(descriptor, i, ThingSerializer(resultSerializer)) | ||
else -> throw SerializationException("Unknown index $i") | ||
} | ||
} | ||
input.endStructure(descriptor) | ||
if (action == null || id == null || result == null) throw SerializationException("Missing fields") | ||
return when(action) { | ||
"CREATE" -> LiveQueryAction.Create(id, (result as Thing.Record<T>).result) | ||
"UPDATE" -> LiveQueryAction.Update(id, (result as Thing.Record<T>).result) | ||
"DELETE" -> LiveQueryAction.Delete(id, (result as Thing.Reference).id) | ||
else -> throw SerializationException("Unknown action $action") | ||
} | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: LiveQueryAction<T>) { | ||
TODO("Not yet implemented") | ||
} | ||
|
||
} |
2 changes: 1 addition & 1 deletion
2
...n/uk/gibby/driver/rpc/model/RpcRequest.kt → ...n/uk/gibby/driver/model/rpc/RpcRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.