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

io.wavebeans.execution.podproxy.PodProxyIterator.kt Maven / Gradle / Ivy

package io.wavebeans.execution.podproxy

import io.wavebeans.execution.BushCallerRepository
import io.wavebeans.execution.PodDiscovery
import io.wavebeans.execution.config.ExecutionConfig
import io.wavebeans.execution.medium.Medium
import io.wavebeans.execution.medium.value
import io.wavebeans.execution.pod.PodKey
import mu.KotlinLogging
import java.util.concurrent.TimeUnit


class PodProxyIterator(
        val sampleRate: Float,
        val pod: PodKey,
        val readingPartition: Int,
        val podDiscovery: PodDiscovery = PodDiscovery.default,
        val bushCallerRepository: BushCallerRepository = BushCallerRepository.default(podDiscovery),
        val prefetchBucketAmount: Int = ExecutionConfig.prefetchBucketAmount,
        val partitionSize: Int = ExecutionConfig.partitionSize
) : Iterator {

    companion object {
        private val log = KotlinLogging.logger { }
    }

    private val bush = podDiscovery.bushFor(pod)
    private val caller = bushCallerRepository.create(bush, pod)
    private val iteratorKey: Long

    init {
        iteratorKey = caller.call("iteratorStart?sampleRate=$sampleRate&partitionIdx=${readingPartition}")
                .get(5000, TimeUnit.MILLISECONDS).value()
        log.trace { "Created iterator [Pod=$pod] iteratorKey=$iteratorKey" }
    }

    private var buckets: List? = null
    private var bucketPointer = 0
    private var pointer = 0
    private var nextEl: Any? = null

    override fun hasNext(): Boolean {
        if (nextEl != null) return true
        return tryReadNextEl()
    }

    override fun next(): Any {
        if (nextEl != null) {
            val el = nextEl!!
            nextEl = null
            return el
        }
        if (tryReadNextEl()) {
            val el = nextEl
            nextEl = null
            return el!!
        } else {
            throw NoSuchElementException("Pod $pod has no more buckets")
        }
    }

    private fun tryReadBuckets(): List? {
        if (buckets == null || bucketPointer >= buckets?.size ?: 0) {
            log.trace { "[$this] Calling iteratorNext(pod=$pod, iteratorKey=$iteratorKey)" }

            val podCallResult = caller.call(
                    "iteratorNext" +
                            "?iteratorKey=$iteratorKey" +
                            "&buckets=$prefetchBucketAmount"
            ).get(5000, TimeUnit.MILLISECONDS)

            if (podCallResult.exception != null) {
                throw IllegalStateException("Error while trying to read next bucket [iteratorKey=$iteratorKey,buckets=$buckets]", podCallResult.exception)
            }
            if (podCallResult.isNull()) {
                log.trace { "[$this] iteratorNext(pod=$pod, iteratorKey=$iteratorKey) returned null" }
                buckets = null
                bucketPointer = 0
                pointer = 0
                return null
            }
            buckets = podCallResult.value()
            log.trace { "[$this] iteratorNext(pod=$pod, iteratorKey=$iteratorKey) result was converted to buckets=$buckets" }
            bucketPointer = 0
            pointer = 0
        }
        return buckets
    }

    private fun tryReadNextEl(): Boolean {
        val s = tryReadBuckets() ?: return false
        val bucket = s[bucketPointer]
        val el = bucket.extractElement(pointer) ?: return false

        if (++pointer >= partitionSize) {
            pointer = 0
            bucketPointer++
        }

        nextEl = el
        return true
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy