private function extract($data): iterable
    {
        $items = null === $this->extract ? $data : ($this->extract)($data, $this);

        if (null === $items) {
            $items = new \EmptyIterator();
        }

        if (!\is_iterable($items)) {
            throw new EtlException('Could not extract data.');
        }

        try {
            foreach ($items as $key => $item) {
                try {
                    $this->shouldSkip = false;
                    $this->eventDispatcher->dispatch(new ItemEvent(EtlEvents::EXTRACT, $item, $key, $this));
                    yield $key => $item;
                } catch (\Exception $e) {
                    continue;
                }
            }
        } catch (\Throwable $e) {
            /** @var ItemExceptionEvent $event */
            $event = $this->eventDispatcher->dispatch(new ItemExceptionEvent(EtlEvents::EXTRACT_EXCEPTION, $item ?? null, $key ?? null, $this, $e));
            if ($event->shouldThrowException()) {
                throw $e;
            }
        }
    }