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

feat: development Stuff #4

Merged
merged 12 commits into from
Jan 13, 2023
37 changes: 23 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
# mixtape • usagi
# Usagi

> a kotlin multi-platform [rabbitmq](https://rabbitmq.org) client
A kotlin multi-platform AMQP 0.9.1 client.

- ⚡ powered by [kotlin coroutines](https://github.com/kotlin/kotlinx.coroutines)
- 🚀 uses [ktor](https://ktor.io)
- 😎 modern api
- ⚡ Powered by [kotlin coroutines](https://github.com/kotlin/kotlinx.coroutines)
- 🚀 Uses [ktor](https://ktor.io)
- 😎 Idiomatic Kotlin API

> **Warning**
> Usagi is in Alpha, bugs may be ahead!

## installation
**We are looking for contributors! If you are looking for a kotlin multiplatform AMQP client please consider opening PRs and Issues, it is very appreciated.**

## Installation

current version: *coming soon*

#### 🐘 docker
#### 🐘 Gradle

```kotlin
repositories {
Expand All @@ -22,20 +24,23 @@ repositories {

dependencies {
// common:
implementation("mixtape.oss.usagi:usagi:{VERSION}")
implementation("dimensional.usagi:usagi:{VERSION}")
}
```

## usage
## Usage

> **Note**
> This API is not final, it may change in the future.

**create a channel:**
**Create a Channel:**

```kotlin
val connection = Usagi.connect("amqp://guest:guest@localhost:5672")
val channel = connection.channels.create() ?: error("Unable to create channel")
```

**using exchanges & queues**
**Using Exchanges & Queues**
```kotlin
channel.exchange.declare {
exchange = "my-exchange"
Expand All @@ -49,7 +54,7 @@ channel.queue.bind {
}
```

**publishing messages:**
**Publishing Messages:**
```kotlin
channel.basic.publish {
data = "Hello, World!".decodeToString()
Expand All @@ -65,7 +70,7 @@ channel.basic.publish {
}
```

**consuming messages:**
**Consuming Messages:**
```kotlin
val consumer = channel.basic.consume {
exchangeName = "my-exchange"
Expand All @@ -78,8 +83,12 @@ consumer.on<MessagePublishedEvent> {
}
```

## acknowledgements
## Acknowledgements

- a bit of the internal connection/channel code was adapted from the [official rabbitmq java client](https://github.com/rabbitmq/rabbitmq-java-client)
- [amqp 0.9.1 spec](https://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf)
- [amqp 0.9.1 doc](https://www.rabbitmq.com/resources/specs/amqp-xml-doc0-9-1.pdf)

---

[Dimensional Fun](https://dimensional.fun)
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
- [ ] connections
* [ ] handle consumer cancellation

probably more that i need to write down but ill do that later!
probably more that I need to write down but ill do that later!
120 changes: 100 additions & 20 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import codegen.GenerateAMQPClasses
import lol.dimensional.gradle.dsl.Version
import lol.dimensional.gradle.dsl.ReleaseType
import lol.dimensional.gradle.dsl.by

plugins {
kotlin("multiplatform")
`maven-publish`

kotlin("plugin.serialization") version "1.7.10"
kotlin("multiplatform")
kotlin("plugin.serialization") version "1.8.0"
}

allprojects {
group = "mixtape.oss.usagi"
val versionRef = Version(0, 0, 1, release = ReleaseType.Snapshot)
version = "$versionRef"
group = "dimensional.usagi"

repositories {
mavenCentral()
repositories {
mavenCentral()

maven(url = "https://maven.dimensional.fun/releases")
maven(url = "https://jitpack.io")
}
}

tasks {
create<GenerateAMQPClasses>("generateAmqpClasses") {
outputDirectory.set(file("src/commonGenerated"))
}
maven(url = "https://maven.dimensional.fun/releases")
maven(url = "https://jitpack.io")
}

kotlin {
explicitApi()

jvm {
withJava()

compilations.all {
kotlinOptions.jvmTarget = compiler.jvm.target
}
Expand All @@ -37,7 +37,7 @@ kotlin {
}

jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(11)) // "8"
languageVersion by JavaLanguageVersion.of(11)
}

linuxX64()
Expand All @@ -51,15 +51,95 @@ kotlin {
kotlin.srcDir("src/commonGenerated")

dependencies {
implementation(libs.bundles.common)
implementation(libs.ktor.network)
implementation(libs.kyuso)
implementation(kotlin("stdlib"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")

implementation("mixtape.oss:kyuso:1.0.2")

implementation("io.github.microutils:kotlin-logging:2.1.23")

implementation("io.ktor:ktor-network:2.2.2")
implementation("io.ktor:ktor-network-tls:2.2.2")
implementation("io.ktor:ktor-http:2.2.2")
}
}

getByName("jvmTest").dependencies {
implementation(libs.logback)
implementation("com.rabbitmq:amqp-client:5.15.0")
implementation("ch.qos.logback:logback-classic:1.2.11")
}
}
}

tasks {
val jvmMainClasses by named("jvmMainClasses") {
dependsOn("compileJava")
}

val jvmTestClasses by named("jvmTestClasses") {
dependsOn("compileJava")
}

create<GenerateAMQPClasses>("generateAmqpClasses") {
outputDirectory by file("src/commonGenerated")
}

publishing {
repositories {
dimensionalFun(
versionRef.repository,
System.getenv("REPO_ALIAS"),
System.getenv("REPO_TOKEN"),
true
)
}

publications.filterIsInstance<MavenPublication>().forEach { publication ->
publication.pom {
name by project.name
description by "\uD83D\uDC30 kotlin multi-platform rabbitmq client"
url by "https://github.com/dimensional-fun/usagi"

organization {
name by "Dimensional Fun"
url by "https://www.dimensional.fun"
}

developers {
developer {
name by "Dimensional Fun"
email by "[email protected]"
url by "https://opensource.dimensional.fun"
}

developer {
name by "melike2d"
email by "[email protected]"
url by "https://2d.gay"
}
}

licenses {
license {
name by "Apache-2.0"
url by "https://opensource.org/licenses/Apache-2.0"
}
}

issueManagement {
system by "GitHub"
url by "https://github.com/dimensional-fun/usagi/issues"
}

scm {
connection by "scm:git:ssh://github.com/dimensional-fun/usagi.git"
developerConnection by "scm:git:ssh://[email protected]/dimensional-fun/usagi.git"
url by "https://github.com/dimensional-fun/usagi"
}
}
}
}
}

7 changes: 3 additions & 4 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ repositories {

dependencies {
/* gradle bullshit */
implementation(kotlin("gradle-plugin", version = "1.7.10"))
implementation(kotlin("gradle-plugin", version = "1.8.0"))

implementation(gradleApi())
implementation(localGroovy())

/* misc */
// implementation("org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.17.3")
implementation("fun.dimensional.gradle:gradle-tools:1.0.3")
implementation("fun.dimensional.gradle:gradle-tools:1.1.2")

/* used for code-generation */
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation("com.squareup:kotlinpoet:1.12.0")
}
16 changes: 9 additions & 7 deletions buildSrc/src/main/kotlin/codegen/classes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fun generateAMQP(name: String, classes: List<AMQP.Class>): FileSpec {
fun generateAMQPObject(name: String, amqpClasses: List<AMQP.Class>): TypeSpec {
val classHolder = TypeSpec.objectBuilder(name)
.addModifiers(KModifier.PUBLIC)
//.addKdoc("Container class for auto-generated AMQP classes & their methods.")
// .addKdoc("Container class for auto-generated AMQP classes & their methods.")

for (amqpClass in amqpClasses) {
val spec = generateAMQPClass(amqpClass)
Expand All @@ -37,11 +37,10 @@ fun TypeSpec.Builder.amqpReadMethodFromFunction(amqpClasses: List<AMQP.Class>):
.returns(METHOD)

spec.addCode(
"""
|val classId = reader.readShortUnsigned().toInt()
|val methodId = reader.readShortUnsigned().toInt()
|return when (classId) {
|""".trimMargin()
"""|val classId = reader.readShortUnsigned().toInt()
|val methodId = reader.readShortUnsigned().toInt()
|return when (classId) {
|""".trimMargin()
)

for (amqpClass in amqpClasses) {
Expand All @@ -56,7 +55,10 @@ fun TypeSpec.Builder.amqpReadMethodFromFunction(amqpClasses: List<AMQP.Class>):

fun AMQP.Class.createWhenMethodId(): String =
"""when (methodId) {
${methods.joinToString("\n") { "|$INDENT${it.id} -> ${normalizedName}.${it.normalizedName}(reader)" }}
${methods.joinToString("\n") {
val expression = "${normalizedName}.${it.normalizedName}"
"|$INDENT${it.id} -> $expression${if (it.arguments.isNotEmpty()) "(reader)" else ""}"
}}
|${INDENT}else -> error("Invalid method id ${"$"}methodId for class ${"$"}classId")
|}
""".replaceIndentByMargin(INDENT)
Expand Down
19 changes: 10 additions & 9 deletions buildSrc/src/main/kotlin/codegen/common.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fun TypeSpec.Builder.amqpToBuilderFunction(parent: AMQP.Parent): TypeSpec.Builde

toBuilder.addCode("return Builder()\n")
for (child in parent.children) {
toBuilder.addCode(" .${child.normalizedName}(${child.normalizedName})\n")
toBuilder.addCode("$INDENT.${child.normalizedName}(${child.normalizedName})\n")
}

return addFunction(toBuilder.build())
Expand All @@ -21,14 +21,15 @@ fun amqpCompanionBuilderFunction(returnType: TypeName): FunSpec {
.addModifiers(KModifier.PUBLIC, KModifier.INLINE, KModifier.OPERATOR)
.addParameter(
ParameterSpec
.builder("block", LambdaTypeName.get(ClassName("", "Builder"), returnType = UNIT))
.defaultValue("{}")
.build())
.addCode("""
|return Builder()
| .apply(block)
| .build()
""".trimMargin())
.builder("block", LambdaTypeName.get(ClassName("", "Builder"), returnType = UNIT))
.defaultValue("{}")
.build()
)
.addCode(
"""|return Builder()
|$INDENT.apply(block)
|$INDENT.build()""".trimMargin()
)
.returns(returnType)
.build()
}
3 changes: 2 additions & 1 deletion buildSrc/src/main/kotlin/codegen/constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import com.squareup.kotlinpoet.ClassName
val protocolPackage = project.rootPackage + ".protocol"
val channelPackage = project.rootPackage + ".channel"

val INDENT = " "
//val INDENT = " "
val INDENT = " "

val DELEGATES = ClassName("kotlin.properties", "Delegates")

Expand Down
Loading