All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.wavebeans.execution.TopologyPartitioner.kt Maven / Gradle / Ivy

package io.wavebeans.execution

import io.wavebeans.lib.Bean
import io.wavebeans.lib.SinkBean
import io.wavebeans.lib.SinglePartitionBean
import io.wavebeans.lib.WaveBeansClassLoader
import kotlin.reflect.full.isSubclassOf

fun Topology.partition(partitionsCount: Int): Topology {
    check(partitionsCount > 0) { "Partitions count should be > 0" }
    val beanRefs = mutableListOf()
    val links = mutableListOf()
    val replacedBeans = mutableMapOf>()
    val handledBeans = mutableSetOf()


    fun handleBean(beanRef: BeanRef, level: Int = 1) {
        val beanClazz = WaveBeansClassLoader.classForName(beanRef.type).kotlin
        val linkedBeans = this.links
                .filter { it.from == beanRef.id }
                .map { l -> this.refs.first { it.id == l.to } }
        if (linkedBeans.isEmpty() || handledBeans.contains(beanRef)) {
            return
        }
        handledBeans += beanRef

        for (linkedBeanRef in linkedBeans) {
            val linkedBeanClazz = WaveBeansClassLoader.classForName(linkedBeanRef.type).kotlin
            val (newLinks, newBeans) = when {
                linkedBeanClazz.isSubclassOf(SinglePartitionBean::class) && beanClazz.isSubclassOf(Bean::class) -> {
                    val partitionedBeans = replacedBeans.getValue(beanRef)
                    val newBeans = replacedBeans[linkedBeanRef] ?: listOf(linkedBeanRef)
                    val newLinks = partitionedBeans
                            .map {
                                val bean = newBeans.first()
                                val currentLink = this.links.first { l -> it.id == l.from && bean.id == l.to }
                                BeanLink(
                                        from = it.id,
                                        fromPartition = it.partition,
                                        to = bean.id,
                                        toPartition = 0,
                                        order = currentLink.order
                                )
                            }

                    Pair(newLinks, newBeans)
                }
                linkedBeanClazz.isSubclassOf(Bean::class) && beanClazz.isSubclassOf(SinglePartitionBean::class) -> {
                    val newBeans = replacedBeans[linkedBeanRef]
                            ?: (0 until partitionsCount).map { linkedBeanRef.copy(partition = it) }
                    val newLinks = newBeans
                            .map {
                                val currentLink = this.links.first { l -> beanRef.id == l.from && it.id == l.to }
                                BeanLink(
                                        from = beanRef.id,
                                        fromPartition = 0,
                                        to = it.id,
                                        toPartition = it.partition,
                                        order = currentLink.order
                                )
                            }

                    Pair(newLinks, newBeans)
                }
                linkedBeanClazz.isSubclassOf(Bean::class) && beanClazz.isSubclassOf(Bean::class) -> {
                    val newBeans = replacedBeans[linkedBeanRef]
                            ?: (0 until partitionsCount).map { linkedBeanRef.copy(partition = it) }
                    val newLinks = newBeans
                            .map { newBean ->
                                val currentLink = this.links.first { l -> beanRef.id == l.from && newBean.id == l.to }
                                BeanLink(
                                        from = beanRef.id,
                                        fromPartition = newBean.partition,
                                        to = newBean.id,
                                        toPartition = newBean.partition,
                                        order = currentLink.order
                                )
                            }

                    Pair(newLinks, newBeans)
                }
                else -> throw UnsupportedOperationException("Not supported linkedBeanClazz=$linkedBeanClazz, beanClazz=$beanClazz")
            }

            links += newLinks
            if (linkedBeanRef !in replacedBeans.keys) {
                beanRefs += newBeans
                replacedBeans[linkedBeanRef] = newBeans
                handleBean(linkedBeanRef, level + 1)
            }

        }
    }

    this.refs.filter { WaveBeansClassLoader.classForName(it.type).kotlin.isSubclassOf(SinkBean::class) }
            .forEach {
                beanRefs += it
                replacedBeans[it] = listOf(it)
                handleBean(it)
            }


    return Topology(beanRefs, links, partitionsCount)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy