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

Fix inngest.send. Add Event Builder #57

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.inngest.*;
import org.jetbrains.annotations.NotNull;

import java.util.LinkedHashMap;
import java.util.Map;

public class FollowupFunction extends InngestFunction {

Expand All @@ -18,7 +18,7 @@ public InngestFunctionConfigBuilder config(InngestFunctionConfigBuilder builder)
}

@Override
public LinkedHashMap<String, Object> execute(@NotNull FunctionContext ctx, @NotNull Step step) {
public Map<String, Object> execute(@NotNull FunctionContext ctx, @NotNull Step step) {
System.out.println("-> follow up handler called " + ctx.getEvent().getName());
return ctx.getEvent().getData();
}
Expand Down
4 changes: 2 additions & 2 deletions inngest/src/main/kotlin/com/inngest/Comm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import java.io.IOException

data class ExecutionRequestPayload(
val ctx: ExecutionContext,
val event: Event,
val events: List<Event>,
val event: InngestEvent,
val events: List<InngestEvent>,
val steps: MemoizedState,
)

Expand Down
69 changes: 64 additions & 5 deletions inngest/src/main/kotlin/com/inngest/Event.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package com.inngest

data class Event(
import com.beust.klaxon.Json

/**
* An internal class used for parsing events sent to Inngest functions
*/
internal data class Event(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After propagating InngestEvent to enough places to get this PR to compile, this Event is no longer used. I don't know if the intent was to convert external InngestEvents to internal Events somewhere, but I wasn't sure where so I'm punting on that for this PR

val id: String,
val name: String,
val data: LinkedHashMap<String, Any>,
Expand All @@ -9,7 +14,61 @@ data class Event(
val v: Any? = null,
)

// data class EventAPIResponse(
// val ids: Array<String>,
// val status: String,
// )
/**
* Create an event to send to Inngest
*/
data class InngestEvent
@JvmOverloads
constructor(
val name: String,
val data: Map<String, Any>,
@Json(serializeNull = false)
val user: Map<String, Any>? = null,
@Json(serializeNull = false)
val id: String? = null,
@Json(serializeNull = false)
val ts: Long? = null,
@Json(serializeNull = false)
val v: String? = null,
)

/**
* Construct a new Inngest Event via builder
*/
class InngestEventBuilder(
val name: String,
val data: Map<String, Any>,
) {
private var id: String? = null
private var user: Map<String, Any>? = null
private var ts: Long? = null
private var v: String? = null

fun id(id: String): InngestEventBuilder = apply { this.id = id }

fun ts(ts: Long): InngestEventBuilder = apply { this.ts = ts }

fun user(user: Map<String, Any>) = apply { this.user = user }

fun v(v: String): InngestEventBuilder = apply { this.v = v }

fun build(): InngestEvent {
return InngestEvent(
name,
data,
user,
id,
ts,
v,
)
}
}

/**
* The response from the Inngest Event API including the ids of any event created
* in the order of which they were included in the request
*/
data class SendEventsResponse(
val ids: Array<String>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR originally changed this from Array to List which I think is a good change, but to reduce scope for this PR I am punting on it to a follow up

val status: Int,
)
4 changes: 2 additions & 2 deletions inngest/src/main/kotlin/com/inngest/Function.kt
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ internal class InternalFunctionConfig
* Includes event(s) and other run information
*/
data class FunctionContext(
val event: Event,
val events: List<Event>,
val event: InngestEvent,
val events: List<InngestEvent>,
val runId: String,
val fnId: String,
val attempt: Int,
Expand Down
57 changes: 52 additions & 5 deletions inngest/src/main/kotlin/com/inngest/Inngest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.inngest

import com.beust.klaxon.Klaxon
import java.io.IOException
import java.net.ConnectException

class Inngest
@JvmOverloads
Expand Down Expand Up @@ -36,11 +36,58 @@ class Inngest
fun send(events: Array<InngestEvent>): SendEventsResponse? {
val request = httpClient.build("$baseUrl/e/$eventKey", events)

return httpClient.send(request) lambda@{ response ->
// TODO: Handle error case
if (!response.isSuccessful) throw IOException("Unexpected code $response")
try {
return httpClient.send(request) lambda@{ response ->
if (!response.isSuccessful) {
// TODO - Attempt to parse the HTTP response and get error from JSON body to pass here
throw InngestSendEventBadResponseCodeException(response.code)
}

return@lambda Klaxon().parse<SendEventsResponse>(response.body!!.charStream())
val responseBody = response.body!!.charStream()
try {
val sendEventsResponse = Klaxon().parse<SendEventsResponse>(responseBody)
if (sendEventsResponse != null) {
return@lambda sendEventsResponse
}
} catch (e: Exception) {
throw InngestSendEventInvalidResponseException(responseBody.toString())
}
// If we haven't successfully parsed and returned a valid SendEventsResponse
// by this point, throw an exception
throw InngestSendEventInvalidResponseException(responseBody.toString())
}
} catch (e: ConnectException) {
throw InngestSendEventConnectException(e.message!!)
} catch (e: Exception) {
throw InngestSendEventException(e.message!!)
}
}
}

/**
* A generic exception occurred while sending events
*/
open class InngestSendEventException(
message: String,
) : Exception("Failed to send event: $message")

/**
* A failure occurred establishing a connection to the Inngest Event API
*/
class InngestSendEventConnectException(
message: String,
) : InngestSendEventException(message)

/**
* The Inngest Event API returned a non-successful HTTP status code
*/
class InngestSendEventBadResponseCodeException(
code: Int,
) : InngestSendEventException("Bad response code: $code")

/**
* The Inngest Event API returned a response that was not parsable
*/
class InngestSendEventInvalidResponseException(
message: String,
) : InngestSendEventException("Unable to parse response: $message")
22 changes: 1 addition & 21 deletions inngest/src/main/kotlin/com/inngest/Step.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,6 @@ import java.time.Duration
typealias MemoizedRecord = HashMap<String, Any>
typealias MemoizedState = HashMap<String, MemoizedRecord>

data class InngestEvent(
val name: String,
val data: Any,
)

data class SendEventsResponse(
val ids: Array<String>,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as SendEventsResponse

return ids.contentEquals(other.ids)
}

override fun hashCode(): Int = ids.contentHashCode()
}

class StepInvalidStateTypeException(
val id: String,
val hashedId: String,
Expand Down Expand Up @@ -234,7 +214,7 @@ class Step(
val stepState = state.getState<Array<String>>(hashedId, "event_ids")

if (stepState != null) {
return SendEventsResponse(stepState)
return SendEventsResponse(stepState, 200)
}
throw Exception("step state expected sendEvent, got something else")
} catch (e: StateNotFound) {
Expand Down
26 changes: 26 additions & 0 deletions inngest/src/test/kotlin/com/inngest/InngestEventBuilderTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.inngest

import kotlin.test.Test
import kotlin.test.assertEquals

class InngestEventBuilderTest {
@Test
fun constructorOnlyWithRequiredParameters() {
val event =
InngestEventBuilder("test-name", mapOf())
.build()
assertEquals(InngestEvent("test-name", mapOf()), event)
}

@Test
fun optionalParameters() {
val event =
InngestEventBuilder("test-name", mapOf())
.user(mapOf("userId" to 5))
.id("test-id")
.ts(100)
.v("1.0")
.build()
assertEquals(InngestEvent("test-name", mapOf(), mapOf("userId" to 5), "test-id", 100, "1.0"), event)
}
}