From 1cf6c59e8ae04723e7f004588ea4cb73b448636d Mon Sep 17 00:00:00 2001 From: RTAkland Date: Sat, 17 Jan 2026 23:34:34 +0800 Subject: [PATCH] Remove readme --- README-zh.md | 187 ----------------------------------------------- README.md | 201 --------------------------------------------------- 2 files changed, 388 deletions(-) delete mode 100644 README-zh.md delete mode 100644 README.md diff --git a/README-zh.md b/README-zh.md deleted file mode 100644 index a3c0a4c..0000000 --- a/README-zh.md +++ /dev/null @@ -1,187 +0,0 @@ -# Kotlin cloudflare worker - -纯Kotlin编写的库,可以在Cloudflare worker上运行Kotlin/JS - -# 快速开始 - -## 配置 - -> 项目依赖于Kotlin协程库, 请确保协程库版本号大于`1.10.2` - -```kotlin -plugins { - kotlin("multiplatform") version "2.2.21" -} - -repositories { - mavenCentral() - maven("https://repo.maven.rtast.cn/releases") -} -``` - -```kotlin -// 最新版本请前往下方链接查看 -// https://next.pkg.rtast.cn/#/releases/cn/rtast/kotlin-cfworker/core/ -implementation("cn.rtast.kotlin-cfworker:core:1.0.2") -``` - -## Hello world程序 - -```kotlin -kotlin { - js(IR) { - nodejs { - outputModuleName = "kotlin-cloudflare-worker" - binaries.executable() - } - } -} -``` - -> Minimal hello world app - -```kotlin -/** - * 不要修改这个函数的任何内容 - */ -fun main() { - @Suppress("unused_expression") - val eventListener = EventListener { event -> - val dyn = event.asDynamic() - event.asDynamic().respondWith(handleRequest(dyn.request as Request)) - Unit - } - js("addEventListener('fetch', eventListener)") -} - -/** - * 这里是处理http请求的函数 - */ -@JsExport -fun handleRequest(request: Request): Promise = GlobalScope.promise { - val server = WorkerApplication().apply { - route("/") { - respondText("Hello kotlin cloudflare worker") - } - } - return@promise server.handle(request) -} - -``` - -> 在本地运行之前需要先安装wrangler - -在项目根目录创建一个名为`wrangler.toml`的文件,然后将下面的内容复制进去并修改为你自己的信息 - -```toml -name = "kotlin-cloudflare-worker" # 可以是任何名字 -account_id = "" -workers_dev = false -preview_urls = false -compatibility_date = "2022-08-11" -main = "kotlin-cloudflare-worker.js" # 必须和`outputModuleName`一致 -``` - -运行gradle任务编译出js `gradlew compileProductionExecutableKotlinJs`, -将wrangler.toml复制到 `build/compileSync/js/main/productionExecutable/kotlin`, -并且进入该目录下运行`wrangler dev` - -## 部署 - -使用`wrangler deploy`来部署到cloudflare worker, 在此之前你需要先使用`wrangler login`来登录 - -# 注意事项 - -Cloudflare worker 使用V8引擎来驱动js脚本,线程模型为单线程,所有事件均由event loop(事件循环)驱动,在此之外的所有任务 -都会被drop, 所以不要使用协程库中的launch或任何可以凭空创建出一个挂起作用域的函数来调用suspend函数, 取而代之的是你需要从 -`handleRequest`方法中传播`CoroutineScope`(suspend), 就像下面这样 - -```kotlin -// 不要使用这种方法 -val scope = CoroutineScope(Dispatcher.DEFAULT) - -fun blockingFunction() { - scope.launch { - // 这里的代码永远不会被执行 - } -} - -// 使用下面的代码来正确的调用suspend函数 - -fun main() { - @Suppress("unused_expression") - val eventListener = EventListener { event -> - val dyn = event.asDynamic() - event.asDynamic().respondWith(handleRequest(dyn.request as Request)) - Unit - } - js("addEventListener('fetch', eventListener)") -} - -@JsExport -fun handleRequest(request: Request): Promise = GlobalScope.promise { - return Promise.resolve(Response("Hello")) -} -``` - -# Http 客户端 - -不要使用ktor来作为http客户端, 因为cloudflare worker不是一个标准的nodejs环境, 你需要使用 fetch -`cn.rtast.cfworker.client.fetch` 来发送http请求, 注意不是`window.fetch`, `window.fetch`是浏览器API - -# Websocket - -仅支持Websocket服务器 - -> 使用类似ktor的语法注册websocket端点 - -```kotlin -@JsExport -fun handleRequest(request: Request): Promise = GlobalScope.promise { - val server = WorkerApplication().apply { - route("/") { - respondText("Hello kotlin cloudflare worker") - } - - webSocket("/ws") { - onMessage { - println(it.readText()) - } - - onClose { - } - } - } - return@promise server.handle(request) -} -``` - -# ByteArray 和 ByteBuffer 转换 - -```kotlin -import cn.rtast.cfworker.util.toByteArray -import cn.rtast.cfworker.util.toArrayBuffer - -val bb: ByteBuffer = ... -// 将ByteBuffer转换为ByteArray -val ba: ByteArray = bb.toByteArray() - -// 将ByteArray转换为ByteBuffer -val bb2: ByteBuffer = ba.toArrayBuffer() -``` - -# CPU时间限制 - -cloudflare worker 免费版本限制处理每个请求的CPU时间为10ms(不包括IO等待时间), 如果你需要执行CPU密集型任务或需要更高的配额, -请考虑升级到Workers paid或使用JS来减少标准库和协程库的加载时间. - -即使使用此库注册了超过15个api端点,并且都具备文件处理功能,每个请求占用的cpu时间平均值不超过10ms+-2ms, -在冷启动时处理首次请求时间会大幅增加,最高可达50ms,但worker仍然可以处理并返回请求. - -![avg-cpu-time](./images/avg-cpu-time.png) - -> 上图反应了过去24小时每个请求的平均cpu时间(P50) - -# 已经使用此项目的实例 - -https://repo.maven.rtast.cn \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 6a666a2..0000000 --- a/README.md +++ /dev/null @@ -1,201 +0,0 @@ -# Kotlin cloudflare worker - -A library to running kotlin/js on cloudflare worker. - - - -# Get started - -## Setup - -> `kotlinx.coroutines` is required - -```kotlin -plugins { - kotlin("multiplatform") version "2.2.21" -} - -repositories { - mavenCentral() - maven("https://repo.maven.rtast.cn/releases") -} -``` - -```kotlin -// to get latest version of this lib, go to -// https://next.pkg.rtast.cn/#/releases/cn/rtast/kotlin-cfworker/core/ -implementation("cn.rtast.kotlin-cfworker:core:1.0.2") -``` - -## Run app - -```kotlin -kotlin { - js(IR) { - nodejs { - outputModuleName = "kotlin-cloudflare-worker" - binaries.executable() - } - } -} -``` - -> Minimal hello world app - -```kotlin -/** - * DO NOT EDIT THIS FUNCTION - */ -fun main() { - @Suppress("unused_expression") - val eventListener = EventListener { event -> - val dyn = event.asDynamic() - event.asDynamic().respondWith(handleRequest(dyn.request as Request)) - Unit - } - js("addEventListener('fetch', eventListener)") -} - -@JsExport -fun handleRequest(request: Request): Promise = GlobalScope.promise { - val server = WorkerApplication().apply { - route("/") { - respondText("Hello kotlin cloudflare worker") - } - } - return@promise server.handle(request) -} - -``` - -> Before run worker locally, you need to install wrangler and login - -First, create `wrangler.toml` in your root project and configure it - -```toml -name = "kotlin-cloudflare-worker" # any name you want -account_id = "" -workers_dev = false -preview_urls = false -compatibility_date = "2022-08-11" -main = "kotlin-cloudflare-worker.js" # Set this value same as `outputModuleName` -``` - -Then run gradle task `gradlew compileProductionExecutableKotlinJs`, -copy wrangler.toml into `build/compileSync/js/main/productionExecutable/kotlin`, -and run `wrangler dev` command in `build/compileSync/js/main/productionExecutable/kotlin`, - -## Deploy - -Run gradle task, copy wrangler.toml, but use `wrangler deploy` to deploy to cloudflare worker - -# Note - -JavaScript uses a single-threaded execution model. All asynchronous work is ultimately driven by the event loop ( -including Kotlin coroutines on JS). - -Therefore, DO NOT create a CoroutineScope(Dispatchers.Default) or launch CPU-bound coroutines, as there is no real -background thread on JS targets. - -All coroutines run on same event loop thread, and all coroutines not in same event loop will be dropped. - -Example: - -```kotlin -// DO NOT DO THIS -val scope = CoroutineScope(Dispatcher.DEFAULT) - -fun blockingFunction() { - scope.launch { - // this block will never execute - } -} - -// Instead of do this - -fun main() { - @Suppress("unused_expression") - val eventListener = EventListener { event -> - val dyn = event.asDynamic() - event.asDynamic().respondWith(handleRequest(dyn.request as Request)) - Unit - } - js("addEventListener('fetch', eventListener)") -} - -@JsExport -fun handleRequest(request: Request): Promise = GlobalScope.promise { - return Promise.resolve(Response("Hello")) -} -``` - -# Http client - -Cloudflare worker is not a standard nodejs environment, do http requests must -use fetch api(not `window.fetch`, this is browser api), use `cn.rtast.cfworker.client.fetch` instead, - -# Websocket - -Only websocket server is supported - -> ktor like expression - -```kotlin -@JsExport -fun handleRequest(request: Request): Promise = GlobalScope.promise { - val server = WorkerApplication().apply { - route("/") { - respondText("Hello kotlin cloudflare worker") - } - - webSocket("/ws") { - onMessage { - println(it.readText()) - } - - onClose { - } - } - } - return@promise server.handle(request) -} -``` - -# ByteArray and ByteBuffer cast - -Kotlin cloudflare worker provided api to mutual conversion, - -```kotlin -import cn.rtast.cfworker.util.toByteArray -import cn.rtast.cfworker.util.toArrayBuffer - -val bb: ByteBuffer = ... -// convert ByteBuffer to ByteArray -val ba: ByteArray = bb.toByteArray() - -// convert ByteArray to ByteBuffer -val bb2: ByteBuffer = ba.toArrayBuffer() -``` - -# CPU Time limit - -Cloudflare worker free tier have a limit of worker cpu limit (10ms, exclude IO waiting time), `kotlin cloudflare worker` -depends on `kotlin-stdlib` and `kotlinx.coroutines`, which are quite heavy*, When performing CPU-bound task, -please carefully consider whether to use JavaScript instead of Kotlin. - -But it works for my maven repository, I registered over 15 api endpoints. -The avg cpu time for each endpoint does not exceed 10ms, but it may increase significantly during -cold start (Over 50-200ms, but still responsible) - -![avg-cpu-time](./images/avg-cpu-time.png) - -> This image shows last 24 hours avg cpu time, see `P50` - -# Real instance - -https://repo.maven.rtast.cn - -> Yes, it the maven repository but built with kotlin/js with this lib \ No newline at end of file