Skip to content

Commit 275ffab

Browse files
committed
Add coroutines-based API with StateFlow extensions
Added coroutines-based API via extension functions to provide a modern approach to working with Socket.IO without modifying the existing callback-based API. Main changes: - Added suspend extension functions: * Manager.openSuspend() - open connection using coroutines * Socket.openSuspend() - open socket using coroutines * Socket.emitSuspend() - emit events using coroutines * Socket.emitSuspend(event, *args) { ack } - emit with ack (trailing lambda) * IO.socketSuspend() - create socket using coroutines - Added StateFlow and Flow extensions: * Manager.stateFlow - track manager state * Socket.connectedFlow - track connection state * Socket.socketIdFlow - track socket ID * Emitter.flow(event) - receive events via Flow * Emitter.flowWithReplay(event, replay) - Flow with replay buffer - Added usage examples (CoroutinesExample.kt): * Basic API usage * Error handling and subscription cancellation * Reconnection with new parameters * Proper resource cleanup * Automatic reconnection handling * Detailed explanation of Flow errors * Importance of subscription order - Added tests (CoroutinesExtensionsTest.kt): * Coverage of all main usage scenarios * Tests for all extension functions * Tests for StateFlow and Flow extensions * Tests for error handling - Updated documentation (README.md): * Added "Coroutines-based API (Recommended)" section * Usage examples for all new functions * Description of all available extension functions All changes are backward compatible - existing callback-based API remains unchanged. New API uses idiomatic Kotlin syntax with trailing lambda for acknowledgements.
1 parent 23153d5 commit 275ffab

6 files changed

Lines changed: 1744 additions & 0 deletions

File tree

README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ kotlin {
3636

3737
## Usage
3838

39+
### Callback-based API (Original)
40+
3941
```kotlin
4042
val opt = IO.Options()
4143
// opt.trustAllCerts = true
@@ -53,11 +55,65 @@ IO.socket("http://localhost:3000", opt) { socket ->
5355
}
5456
```
5557

58+
### Coroutines-based API (Recommended)
59+
60+
```kotlin
61+
val opt = IO.Options()
62+
opt.transports = listOf(WebSocket.NAME)
63+
64+
// Create socket using suspend function
65+
val socket = IO.socketSuspend("http://localhost:3000", opt)
66+
67+
// Monitor connection state using StateFlow
68+
socket.connectedFlow.collect { connected ->
69+
println("Socket connected: $connected")
70+
}
71+
72+
// Monitor manager state using StateFlow
73+
socket.io.stateFlow.collect { state ->
74+
println("Manager state: $state")
75+
}
76+
77+
// Listen to events using Flow
78+
socket.flow(Socket.EVENT_CONNECT).collect { args ->
79+
println("Connected: ${args.joinToString()}")
80+
}
81+
82+
socket.flow("echoBack").collect { args ->
83+
println("EchoBack: ${args.joinToString()}")
84+
}
85+
86+
// Open socket using suspend function
87+
socket.openSuspend()
88+
89+
// Emit event using suspend function
90+
val bin = UnsafeByteStringOperations.wrapUnsafe(byteArrayOf(0x1, 0x3, 0x1, 0x4))
91+
socket.emitSuspend("echo", 1, "2", bin, GMTDate())
92+
93+
// Emit with suspend acknowledgement callback (trailing lambda syntax)
94+
socket.emitSuspend("echoWithAck", 42, "test") { args ->
95+
println("Ack received: ${args.joinToString()}")
96+
}
97+
```
98+
5699
Most of the APIs are the same as socket.io-client-java, here are some differences:
57100

58101
- Create socket is asynchronous, to make it's easier to guarantee thread safety.
59102
- Binary messages can't be nested, because `emit` only accepts String/Boolean/Number/JsonElement/ByteString, other types will be converted to String using `toString()`, so there is no way to put ByteString in JsonElement.
60103

104+
### Available Extension Functions
105+
106+
- `IO.socketSuspend(uri, opt)` - Create socket using coroutines
107+
- `Manager.openSuspend()` - Open manager using coroutines
108+
- `Socket.openSuspend()` - Open socket using coroutines
109+
- `Socket.emitSuspend(event, *args)` - Emit event using coroutines
110+
- `Socket.emitSuspend(event, *args, ack: suspend (Array<out Any>) -> Unit)` - Emit with suspend acknowledgement callback (trailing lambda)
111+
- `Manager.stateFlow` - StateFlow for tracking manager state
112+
- `Socket.connectedFlow` - StateFlow for tracking connection state
113+
- `Socket.socketIdFlow` - StateFlow for tracking socket ID
114+
- `Emitter.flow(event)` - Flow for event streaming
115+
- `Emitter.flowWithReplay(event, replay)` - Flow with replay buffer
116+
61117
### Logging with [kmp-xlog](https://github.com/HackWebRTC/kmp-xlog)
62118

63119
## Development

0 commit comments

Comments
 (0)