Skip to content

Commit

Permalink
More API experiments
Browse files Browse the repository at this point in the history
  • Loading branch information
rorbech committed Dec 5, 2023
1 parent 8e37043 commit 77c5a68
Show file tree
Hide file tree
Showing 9 changed files with 1,078 additions and 1,069 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import io.realm.kotlin.mongodb.ext.customDataAsBsonDocument
import io.realm.kotlin.mongodb.ext.profileAsBsonDocument
import io.realm.kotlin.mongodb.mongo.MongoClient
import io.realm.kotlin.mongodb.sync.SyncConfiguration
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

/**
* A **user** holds the user's metadata and tokens for accessing App Services and Device Sync
Expand Down Expand Up @@ -203,8 +205,8 @@ public interface User {
public suspend fun linkCredentials(credentials: Credentials): User

// TODO Doc
// TODO serializer argument
public fun mongoClient(serviceName: String): MongoClient
@OptIn(ExperimentalKBsonSerializerApi::class)
public fun mongoClient(serviceName: String, eJson: EJson? = null): MongoClient

/**
* Two Users are considered equal if they have the same user identity and are associated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@ package io.realm.kotlin.mongodb.internal

import io.realm.kotlin.mongodb.mongo.MongoClient
import io.realm.kotlin.mongodb.mongo.MongoDatabase
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

@OptIn(ExperimentalKBsonSerializerApi::class)
@PublishedApi
internal class MongoClientImpl(
@PublishedApi
internal val user: UserImpl, override val serviceName: String) : MongoClient {
override fun database(databaseName: String): MongoDatabase = MongoDatabaseImpl(this, databaseName)
internal val user: UserImpl,
override val serviceName: String,
val eJson: EJson,
) : MongoClient {

override fun database(databaseName: String, eJson: EJson?): MongoDatabase =
MongoDatabaseImpl(this, databaseName, eJson ?: this.eJson)

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,94 @@
package io.realm.kotlin.mongodb.internal

import io.realm.kotlin.annotations.ExperimentalRealmSerializerApi
import io.realm.kotlin.mongodb.ext.CallBuilder
import io.realm.kotlin.mongodb.ext.call
import io.realm.kotlin.mongodb.mongo.MongoCollection
import io.realm.kotlin.mongodb.mongo.insertMany
import org.mongodb.kbson.BsonArray
import org.mongodb.kbson.BsonDocument
import org.mongodb.kbson.BsonInt64
import org.mongodb.kbson.BsonString
import org.mongodb.kbson.BsonValue
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson
import org.mongodb.kbson.serialization.decodeFromBsonValue
import org.mongodb.kbson.serialization.encodeToBsonValue

@OptIn(ExperimentalKBsonSerializerApi::class, ExperimentalRealmSerializerApi::class)
@PublishedApi
internal open class MongoCollectionImpl(

internal class MongoCollectionImpl<T, K> @OptIn(ExperimentalKBsonSerializerApi::class) constructor(
@PublishedApi internal val database: MongoDatabaseImpl,
override val name: String,
) : MongoCollection {
val eJson: EJson,
): MongoCollection<T, K> {

val client = this.database.client
val user = client.user
val functions = user.functions


val defaults: Map<String, BsonValue> = mapOf(
"database" to BsonString(database.name),
"collection" to BsonString(name),
)

override suspend fun count(filter: BsonDocument?, limit: Long?): Int {
@OptIn(ExperimentalRealmSerializerApi::class)
return user.functions.call("count") {
@ExperimentalRealmSerializerApi
private suspend inline fun <reified R> call(name: String, crossinline document: MutableMap<String, BsonValue>.()-> Unit): R {
return user.functions.call(name) {
serviceName(client.serviceName)
val args = defaults.toMutableMap()
limit?.let { args.put("limit", BsonInt64(limit)) }
filter?.let { args.put("query", it) }
add(BsonDocument(args))
val doc = defaults.toMutableMap()
document(doc)
add(doc)
}
}

@PublishedApi
internal suspend fun count(filter: BsonDocument? = null, limit: Long? = null): Long {
return call("count") {
filter?.let { put("query", it) }
limit?.let { put("limit", BsonInt64(it)) }
}
}

@PublishedApi
internal suspend fun findOne(filter: BsonDocument? = null, projection: BsonDocument? = null, sort: BsonDocument? = null): BsonValue =
call("findOne") {
filter?.let { put("query", it) }
projection?.let { put("projection", it) }
sort?.let { put("sort", it) }
}

@PublishedApi
internal suspend fun find(filter: BsonDocument? = null, projection: BsonDocument? = null, sort: BsonDocument? = null, limit: Long? = null): BsonValue =
call("find") {
filter?.let { put("query", it) }
projection?.let { put("projection", it) }
sort?.let { put("sort", it) }
limit?.let { put("limit", BsonInt64(it)) }
}

@PublishedApi
internal suspend fun aggregate(pipeline: List<BsonDocument>): List<BsonValue> =
call<BsonValue>("aggregate") { put("pipeline", BsonArray(pipeline)) }.asArray().toList()

@PublishedApi
internal suspend fun insertOne(document: BsonDocument): BsonValue =
call<BsonValue>("insertOne") { put("document", document) }.asDocument()["insertedId"]!!

@PublishedApi
internal suspend fun insertMany(documents: List<BsonDocument>): List<BsonValue> =
call<BsonValue>("insertMany") {
put("documents", BsonArray(documents))
}.asDocument().get("insertedIds")!!.asArray().toList()
}

@ExperimentalRealmSerializerApi
@OptIn(ExperimentalKBsonSerializerApi::class)
@PublishedApi
internal suspend inline fun MongoCollectionImpl.call(name: String, crossinline document: MutableMap<String, BsonValue>.()-> Unit): BsonValue {
return user.functions.call(name) {
serviceName(client.serviceName)
val doc = this@call.defaults.toMutableMap()
document(doc)
add(doc)
}
internal inline fun <reified R> MongoCollectionImpl<*, *>.decodeFromBsonValue(bsonValue: BsonValue): R {
return eJson.decodeFromBsonValue(bsonValue)
}
@OptIn(ExperimentalKBsonSerializerApi::class)
@PublishedApi
internal inline fun <reified R : Any> MongoCollectionImpl<*, *>.encodeToBsonValue(value: R): BsonValue {
return eJson.encodeToBsonValue(value)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,23 @@ package io.realm.kotlin.mongodb.internal

import io.realm.kotlin.mongodb.mongo.MongoCollection
import io.realm.kotlin.mongodb.mongo.MongoDatabase
import io.realm.kotlin.mongodb.mongo.TypedMongoCollection
import io.realm.kotlin.mongodb.mongo.TypedMongoCollectionImpl
import org.mongodb.kbson.BsonValue
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

@PublishedApi
internal class MongoDatabaseImpl(
@OptIn(ExperimentalKBsonSerializerApi::class)
internal class MongoDatabaseImpl constructor(
@PublishedApi
internal val client: MongoClientImpl,
override val name: String,
val eJson: EJson,
) : MongoDatabase {
override fun collection(collectionName: String): MongoCollection =
MongoCollectionImpl(this, collectionName)

override fun typedCollectionbson(collectionName: String): TypedMongoCollection<BsonValue, BsonValue> {
return TypedMongoCollectionImpl(collection(collectionName) as MongoCollectionImpl)
override fun collection(collectionName: String): MongoCollection<BsonValue, BsonValue> {
return MongoCollectionImpl(this, collectionName, this.eJson)
}

override fun <T, R> typedCollection(collectionName: String): TypedMongoCollection<T, R> {
return TypedMongoCollectionImpl(collection(collectionName) as MongoCollectionImpl)
}
override fun <T, K> collection(collectionName: String, eJson: EJson?): MongoCollection<T, K> =
MongoCollectionImpl(this, collectionName, eJson ?: this.eJson)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import io.realm.kotlin.mongodb.mongo.MongoClient
import io.realm.kotlin.mongodb.mongo.MongoCollection
import io.realm.kotlin.mongodb.mongo.MongoDatabase
import kotlinx.coroutines.channels.Channel
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

// TODO Public due to being a transitive dependency to SyncConfigurationImpl
public class UserImpl(
Expand Down Expand Up @@ -185,7 +187,8 @@ public class UserImpl(
}
}

override fun mongoClient(serviceName: String): MongoClient = MongoClientImpl(this, serviceName)
@OptIn(ExperimentalKBsonSerializerApi::class)
override fun mongoClient(serviceName: String, eJson: EJson?): MongoClient = MongoClientImpl(this, serviceName, eJson ?: app.configuration.ejson)

override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package io.realm.kotlin.mongodb.mongo

import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

/**
* The remote MongoClient used for working with data in MongoDB remotely via Realm.
*/
public interface MongoClient {

public val serviceName: String

public fun database(databaseName: String): MongoDatabase
@OptIn(ExperimentalKBsonSerializerApi::class)
public fun database(databaseName: String, eJson: EJson? = null): MongoDatabase
}
Loading

0 comments on commit 77c5a68

Please sign in to comment.