Skip to content

Commit

Permalink
feat: add signals + subscriptions to GraphQL API
Browse files Browse the repository at this point in the history
Expose signals and signal subscriptions via GraphQL API.
  • Loading branch information
saig0 committed Apr 6, 2023
1 parent 20c8d17 commit cc9b32e
Show file tree
Hide file tree
Showing 21 changed files with 466 additions and 63 deletions.
13 changes: 13 additions & 0 deletions data/src/main/kotlin/io/zeebe/zeeqs/data/entity/Signal.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.zeebe.zeeqs.data.entity

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id

@Entity
class Signal(
@Id @Column(name = "key_") val key: Long,
val position: Long,
val name: String,
var timestamp: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.zeebe.zeeqs.data.entity

import javax.persistence.*

@Entity
class SignalSubscription(
@Id @Column(name = "key_") val key: Long,
val position: Long,
val signalName: String,
val processDefinitionKey: Long,
val elementId: String
) {

@Enumerated(EnumType.STRING)
var state: SignalSubscriptionState = SignalSubscriptionState.CREATED
var timestamp: Long = -1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.zeebe.zeeqs.data.entity

enum class SignalSubscriptionState {
CREATED,
DELETED
}
15 changes: 15 additions & 0 deletions data/src/main/kotlin/io/zeebe/zeeqs/data/entity/SignalVariable.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.zeebe.zeeqs.data.entity

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Lob

@Entity
class SignalVariable(
@Id val id: String,
val name: String,
@Lob @Column(name = "value_") val value: String,
val signalKey: Long,
val position: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.zeebe.zeeqs.data.repository

import io.zeebe.zeeqs.data.entity.Signal
import org.springframework.data.repository.PagingAndSortingRepository
import org.springframework.stereotype.Repository

@Repository
interface SignalRepository : PagingAndSortingRepository<Signal, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.zeebe.zeeqs.data.repository

import io.zeebe.zeeqs.data.entity.SignalSubscription
import org.springframework.data.repository.PagingAndSortingRepository
import org.springframework.stereotype.Repository

@Repository
interface SignalSubscriptionRepository : PagingAndSortingRepository<SignalSubscription, Long> {

fun findByProcessDefinitionKey(processDefinitionKey: Long): List<SignalSubscription>

fun findByProcessDefinitionKeyAndSignalName(
processDefinitionKey: Long,
signalName: String
): SignalSubscription?

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.zeebe.zeeqs.data.repository

import io.zeebe.zeeqs.data.entity.SignalVariable
import org.springframework.data.repository.PagingAndSortingRepository
import org.springframework.stereotype.Repository

@Repository
interface SignalVariableRepository : PagingAndSortingRepository<SignalVariable, String> {

fun findBySignalKey(signalKey: Long): List<SignalVariable>

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.zeebe.zeeqs.data.service

data class BpmnElementMetadata(
val jobType: String? = null,
val conditionExpression: String? = null,
val timerDefinition: String? = null,
val errorCode: String? = null,
val calledProcessId: String? = null,
val messageSubscriptionDefinition: MessageSubscriptionDefinition? = null,
val userTaskAssignmentDefinition: UserTaskAssignmentDefinition? = null,
val userTaskForm: UserTaskForm? = null
val jobType: String? = null,
val conditionExpression: String? = null,
val timerDefinition: String? = null,
val errorCode: String? = null,
val calledProcessId: String? = null,
val messageSubscriptionDefinition: MessageSubscriptionDefinition? = null,
val userTaskAssignmentDefinition: UserTaskAssignmentDefinition? = null,
val userTaskForm: UserTaskForm? = null,
val signalName: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.zeebe.zeeqs.graphql.resolvers.connection

import io.zeebe.zeeqs.data.entity.Signal

class SignalConnection(
val getItems: () -> List<Signal>,
val getCount: () -> Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.zeebe.zeeqs.graphql.resolvers.connection

import io.zeebe.zeeqs.data.entity.Signal
import org.springframework.graphql.data.method.annotation.SchemaMapping
import org.springframework.stereotype.Controller

@Controller
class SignalConnectionResolver {

@SchemaMapping(typeName = "SignalConnection", field = "nodes")
fun nodes(connection: SignalConnection): List<Signal> {
return connection.getItems()
}

@SchemaMapping(typeName = "SignalConnection", field = "totalCount")
fun totalCount(connection: SignalConnection): Long {
return connection.getCount()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.zeebe.zeeqs.graphql.resolvers.query

import io.zeebe.zeeqs.data.entity.Signal
import io.zeebe.zeeqs.data.repository.SignalRepository
import io.zeebe.zeeqs.graphql.resolvers.connection.SignalConnection
import org.springframework.data.domain.PageRequest
import org.springframework.data.repository.findByIdOrNull
import org.springframework.graphql.data.method.annotation.Argument
import org.springframework.graphql.data.method.annotation.QueryMapping
import org.springframework.stereotype.Controller

@Controller
class SignalQueryResolver(
val signalRepository: SignalRepository
) {

@QueryMapping
fun signals(
@Argument perPage: Int,
@Argument page: Int
): SignalConnection {
return SignalConnection(
getItems = {
signalRepository.findAll(PageRequest.of(page, perPage)).toList()
},
getCount = {
signalRepository.count()
}
)
}

@QueryMapping
fun signal(@Argument key: Long): Signal? {
return signalRepository.findByIdOrNull(key)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.zeebe.zeeqs.graphql.resolvers.type
import io.zeebe.zeeqs.data.entity.*
import io.zeebe.zeeqs.data.repository.MessageSubscriptionRepository
import io.zeebe.zeeqs.data.repository.ProcessInstanceRepository
import io.zeebe.zeeqs.data.repository.SignalSubscriptionRepository
import io.zeebe.zeeqs.data.repository.TimerRepository
import io.zeebe.zeeqs.data.service.BpmnElementInfo
import io.zeebe.zeeqs.data.service.ProcessService
Expand All @@ -14,29 +15,41 @@ import org.springframework.stereotype.Controller

@Controller
class ProcessResolver(
val processInstanceRepository: ProcessInstanceRepository,
val timerRepository: TimerRepository,
val messageSubscriptionRepository: MessageSubscriptionRepository,
val processService: ProcessService
val processInstanceRepository: ProcessInstanceRepository,
val timerRepository: TimerRepository,
val messageSubscriptionRepository: MessageSubscriptionRepository,
val processService: ProcessService,
private val signalSubscriptionRepository: SignalSubscriptionRepository
) {

@SchemaMapping(typeName = "Process", field = "processInstances")
fun processInstances(
process: Process,
@Argument perPage: Int,
@Argument page: Int,
@Argument stateIn: List<ProcessInstanceState>
process: Process,
@Argument perPage: Int,
@Argument page: Int,
@Argument stateIn: List<ProcessInstanceState>
): ProcessInstanceConnection {
return ProcessInstanceConnection(
getItems = { processInstanceRepository.findByProcessDefinitionKeyAndStateIn(process.key, stateIn, PageRequest.of(page, perPage)).toList() },
getCount = { processInstanceRepository.countByProcessDefinitionKeyAndStateIn(process.key, stateIn) }
getItems = {
processInstanceRepository.findByProcessDefinitionKeyAndStateIn(
process.key,
stateIn,
PageRequest.of(page, perPage)
).toList()
},
getCount = {
processInstanceRepository.countByProcessDefinitionKeyAndStateIn(
process.key,
stateIn
)
}
)
}

@SchemaMapping(typeName = "Process", field = "deployTime")
fun deployTime(
process: Process,
@Argument zoneId: String
process: Process,
@Argument zoneId: String
): String? {
return process.deployTime.let { ResolverExtension.timestampToString(it, zoneId) }
}
Expand All @@ -48,38 +61,45 @@ class ProcessResolver(

@SchemaMapping(typeName = "Process", field = "messageSubscriptions")
fun messageSubscriptions(process: Process): List<MessageSubscription> {
return messageSubscriptionRepository.findByProcessDefinitionKeyAndElementInstanceKeyIsNull(process.key)
return messageSubscriptionRepository.findByProcessDefinitionKeyAndElementInstanceKeyIsNull(
process.key
)
}

@SchemaMapping(typeName = "Process", field = "signalSubscriptions")
fun signalSubscriptions(process: Process): List<SignalSubscription> {
return signalSubscriptionRepository.findByProcessDefinitionKey(processDefinitionKey = process.key)
}

@SchemaMapping(typeName = "Process", field = "elements")
fun elements(
process: Process,
@Argument elementTypeIn: List<BpmnElementType>
process: Process,
@Argument elementTypeIn: List<BpmnElementType>
): List<BpmnElement> {
return processService
.getBpmnElementInfo(process.key)
?.values
?.filter { elementTypeIn.isEmpty() || elementTypeIn.contains(it.elementType) }
?.map { asBpmnElement(process, it) }
?: emptyList()
.getBpmnElementInfo(process.key)
?.values
?.filter { elementTypeIn.isEmpty() || elementTypeIn.contains(it.elementType) }
?.map { asBpmnElement(process, it) }
?: emptyList()
}

private fun asBpmnElement(process: Process, it: BpmnElementInfo) =
BpmnElement(
processDefinitionKey = process.key,
elementId = it.elementId,
elementType = it.elementType
)
BpmnElement(
processDefinitionKey = process.key,
elementId = it.elementId,
elementType = it.elementType
)

@SchemaMapping(typeName = "Process", field = "element")
fun element(
process: Process,
@Argument elementId: String
process: Process,
@Argument elementId: String
): BpmnElement? {
return processService
.getBpmnElementInfo(process.key)
?.get(elementId)
?.let { asBpmnElement(process, it) }
.getBpmnElementInfo(process.key)
?.get(elementId)
?.let { asBpmnElement(process, it) }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.zeebe.zeeqs.graphql.resolvers.type

import io.zeebe.zeeqs.data.entity.Signal
import io.zeebe.zeeqs.data.entity.SignalVariable
import io.zeebe.zeeqs.data.repository.SignalVariableRepository
import org.springframework.graphql.data.method.annotation.Argument
import org.springframework.graphql.data.method.annotation.SchemaMapping
import org.springframework.stereotype.Controller

@Controller
class SignalResolver(
val signalVariableRepository: SignalVariableRepository
) {

@SchemaMapping(typeName = "Signal", field = "timestamp")
fun timestamp(
signal: Signal,
@Argument zoneId: String
): String? {
return signal.timestamp.let { ResolverExtension.timestampToString(it, zoneId) }
}

@SchemaMapping(typeName = "Signal", field = "variables")
fun variables(signal: Signal): List<SignalVariable> {
return signalVariableRepository.findBySignalKey(signalKey = signal.key)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.zeebe.zeeqs.graphql.resolvers.type

import io.zeebe.zeeqs.data.entity.Process
import io.zeebe.zeeqs.data.entity.SignalSubscription
import io.zeebe.zeeqs.data.repository.ProcessRepository
import org.springframework.data.repository.findByIdOrNull
import org.springframework.graphql.data.method.annotation.Argument
import org.springframework.graphql.data.method.annotation.SchemaMapping
import org.springframework.stereotype.Controller

@Controller
class SignalSubscriptionResolver(
val processRepository: ProcessRepository
) {

@SchemaMapping(typeName = "SignalSubscription", field = "timestamp")
fun timestamp(
signalSubscription: SignalSubscription,
@Argument zoneId: String
): String? {
return signalSubscription.timestamp.let { ResolverExtension.timestampToString(it, zoneId) }
}

@SchemaMapping(typeName = "SignalSubscription", field = "process")
fun process(signalSubscription: SignalSubscription): Process? {
return processRepository.findByIdOrNull(id = signalSubscription.processDefinitionKey)
}

@SchemaMapping(typeName = "SignalSubscription", field = "element")
fun element(signalSubscription: SignalSubscription): BpmnElement? {
return BpmnElement(
processDefinitionKey = signalSubscription.processDefinitionKey,
elementId = signalSubscription.elementId
)
}

}
Loading

0 comments on commit cc9b32e

Please sign in to comment.