-
-
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.
- Loading branch information
1 parent
82a6dfb
commit eb1e912
Showing
31 changed files
with
858 additions
and
697 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
48 changes: 0 additions & 48 deletions
48
invirt-mongodb/src/main/kotlin/invirt/data/mongodb/MongoEntity.kt
This file was deleted.
Oops, something went wrong.
29 changes: 0 additions & 29 deletions
29
invirt-mongodb/src/main/kotlin/invirt/data/mongodb/collection.kt
This file was deleted.
Oops, something went wrong.
36 changes: 0 additions & 36 deletions
36
invirt-mongodb/src/main/kotlin/invirt/data/mongodb/mongo-database.kt
This file was deleted.
Oops, something went wrong.
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,52 @@ | ||
package invirt.mongodb | ||
|
||
import com.mongodb.TransactionOptions | ||
import com.mongodb.WriteConcern | ||
import com.mongodb.kotlin.client.ClientSession | ||
import com.mongodb.kotlin.client.MongoClient | ||
import com.mongodb.kotlin.client.MongoDatabase | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.bson.BsonInt64 | ||
import org.bson.Document | ||
import java.net.URI | ||
|
||
private val log = KotlinLogging.logger {} | ||
|
||
class Mongo(private val connectionString: String) { | ||
|
||
val databaseName: String = URI(connectionString).path.replace("^/".toRegex(), "") | ||
|
||
internal val mongoClient: MongoClient by lazy { | ||
MongoClient.create(connectionString) | ||
} | ||
|
||
val database: MongoDatabase by lazy { | ||
val db = mongoClient.getDatabase(databaseName) | ||
db.runCommand(Document("ping", BsonInt64(1))) | ||
log.info { "Successfully pinged MongoDB database '${databaseName}'" } | ||
db | ||
} | ||
|
||
init { | ||
log.info { "MongoDB connection string: ${connectionString.replace("://.*@".toRegex(), "://*****@")}" } | ||
if (databaseName.isEmpty()) { | ||
throw IllegalArgumentException("Database missing from connection string") | ||
} | ||
} | ||
|
||
fun <Result> runInTransaction(block: (ClientSession) -> Result): Result { | ||
val session = mongoClient.startSession() | ||
return try { | ||
session.startTransaction(TransactionOptions.builder().writeConcern(WriteConcern.MAJORITY).build()) | ||
val result = block(session) | ||
session.commitTransaction() | ||
result | ||
} catch (e: Throwable) { | ||
log.error(e) { "MongoDB transaction error: ${e.message}" } | ||
session.abortTransaction() | ||
throw e | ||
} finally { | ||
session.close() | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
invirt-mongodb/src/main/kotlin/invirt/mongodb/StoredEntity.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,29 @@ | ||
package invirt.mongodb | ||
|
||
import java.time.Instant | ||
import kotlin.reflect.full.findAnnotation | ||
|
||
interface StoredEntity { | ||
val id: String | ||
|
||
@Indexed | ||
var version: Long | ||
|
||
@Indexed | ||
val createdAt: Instant | ||
|
||
@Indexed | ||
var updatedAt: Instant | ||
} | ||
|
||
inline fun <reified Entity : StoredEntity> collectionName(): String { | ||
val annotation = Entity::class.findAnnotation<MongoCollection>() | ||
?: throw IllegalStateException("Class ${Entity::class} doesn't have an @CollectionName annotation") | ||
return annotation.name | ||
} | ||
|
||
fun <Entity : StoredEntity> Entity.updated(): Entity { | ||
version++ | ||
updatedAt = mongoNow() | ||
return this | ||
} |
28 changes: 28 additions & 0 deletions
28
invirt-mongodb/src/main/kotlin/invirt/mongodb/annotations.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,28 @@ | ||
package invirt.mongodb | ||
|
||
@Target(AnnotationTarget.CLASS) | ||
@Retention(AnnotationRetention.RUNTIME) | ||
@MustBeDocumented | ||
annotation class MongoCollection(val name: String) | ||
|
||
@Target(AnnotationTarget.PROPERTY) | ||
@Retention(AnnotationRetention.RUNTIME) | ||
@MustBeDocumented | ||
annotation class Indexed( | ||
val order: Order = Order.ASC, | ||
val caseInsensitive: Boolean = true, | ||
vararg val fields: String | ||
) { | ||
|
||
enum class Order { | ||
ASC, | ||
DESC | ||
} | ||
} | ||
|
||
@Target(AnnotationTarget.PROPERTY) | ||
@Retention(AnnotationRetention.RUNTIME) | ||
@MustBeDocumented | ||
annotation class TextIndexed( | ||
vararg val fields: String | ||
) |
36 changes: 36 additions & 0 deletions
36
invirt-mongodb/src/main/kotlin/invirt/mongodb/collection.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,36 @@ | ||
package invirt.mongodb | ||
|
||
import com.mongodb.client.model.ReplaceOptions | ||
import com.mongodb.kotlin.client.ClientSession | ||
import com.mongodb.kotlin.client.MongoCollection | ||
import org.bson.conversions.Bson | ||
|
||
fun <E : StoredEntity> MongoCollection<E>.save(entity: E): E { | ||
replaceOne(byId(entity.id), entity.updated(), ReplaceOptions().upsert(true)) | ||
return entity | ||
} | ||
|
||
fun <E : StoredEntity> MongoCollection<E>.txSave(session: ClientSession, entity: E): E { | ||
replaceOne(session, byId(entity.id), entity.updated(), ReplaceOptions().upsert(true)) | ||
return entity | ||
} | ||
|
||
fun <E : StoredEntity> MongoCollection<E>.get(id: String): E? { | ||
return findOne(byId(id)) | ||
} | ||
|
||
fun <E : StoredEntity> MongoCollection<E>.findOne(filter: Bson): E? { | ||
val list = find(filter).toList() | ||
if (list.size > 1) { | ||
throw IllegalStateException("More than one document found for filter $filter") | ||
} | ||
return list.firstOrNull() | ||
} | ||
|
||
fun <E : StoredEntity> MongoCollection<E>.delete(id: String): Boolean { | ||
return deleteOne(byId(id)).deletedCount == 1L | ||
} | ||
|
||
fun <E : StoredEntity> MongoCollection<E>.txDelete(session: ClientSession, id: String): Boolean { | ||
return deleteOne(session, byId(id)).deletedCount == 1L | ||
} |
2 changes: 1 addition & 1 deletion
2
...c/main/kotlin/invirt/data/mongodb/data.kt → ...db/src/main/kotlin/invirt/mongodb/data.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
...main/kotlin/invirt/data/mongodb/filter.kt → ...src/main/kotlin/invirt/mongodb/filters.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
...c/main/kotlin/invirt/data/mongodb/find.kt → ...db/src/main/kotlin/invirt/mongodb/find.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
38 changes: 8 additions & 30 deletions
38
.../main/kotlin/invirt/data/mongodb/index.kt → ...b/src/main/kotlin/invirt/mongodb/index.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
10 changes: 10 additions & 0 deletions
10
invirt-mongodb/src/main/kotlin/invirt/mongodb/mongo-database.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,10 @@ | ||
package invirt.mongodb | ||
|
||
import com.mongodb.kotlin.client.MongoCollection | ||
import com.mongodb.kotlin.client.MongoDatabase | ||
|
||
inline fun <reified E : StoredEntity> MongoDatabase.collection(): MongoCollection<E> { | ||
val collection = getCollection<E>(collectionName<E>()) | ||
collection.createEntityIndexes() | ||
return collection | ||
} |
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,9 @@ | ||
package invirt.mongodb | ||
|
||
import java.time.Instant | ||
import java.time.temporal.ChronoUnit | ||
|
||
/** | ||
* MongoDB only support millisecond precision | ||
*/ | ||
fun mongoNow(): Instant = Instant.now().truncatedTo(ChronoUnit.MILLIS) |
Oops, something went wrong.