Skip to content

Extract a transport-agnostic network discovery backend and NetworkDiscoveryHook #14996

Description

@rtibbles

This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.

Overview

Kolibri's network discovery — mDNS broadcast plus peer listening — is welded to zeroconf inside KolibriBroadcast and only runs inside the server ProcessBus. Extract a transport-agnostic NetworkDiscoveryBackend and a NetworkDiscoveryHook transport interface, so a platform can supply an alternative transport (e.g. Android native NSD) and run discovery outside the process bus. Zeroconf becomes the default-registered transport. Server-platform behaviour is unchanged.

Complexity: Medium
Target branch: develop

Context

  • KolibriBroadcast (kolibri/core/discovery/utils/network/broadcast.py) implements the zeroconf transport directly (Zeroconf, ServiceBrowser, ServiceInfo, interface/address handling).
  • It also owns the transport-agnostic machinery: broadcast-id lifecycle, the KolibriBroadcastEvents bus, and listener dispatch.
  • NetworkLocationListener (.../network/search.py) turns those events into DynamicNetworkLocation rows via the add_dynamic_network_location / remove_dynamic_network_location tasks.
  • NetworkLocationListener is already transport-agnostic.
  • ZeroConfPlugin (kolibri/utils/server/__init__.py:295) runs inside the server ProcessBus.
  • It instantiates KolibriBroadcast, attaches the listeners, and monitors address changes every 5s.
  • The existing NetworkLocationDiscoveryHook / NetworkLocationBroadcastHook are notification-only.
  • There is no interface for supplying discovery.

The Change

  • Define @define_hook(only_one_registered=True) class NetworkDiscoveryHook: register(instance), update(instance), unregister(), start_listening(on_add, on_update, on_remove), stop_listening().
  • Split KolibriBroadcast into a concrete NetworkDiscoveryBackend (transport-agnostic) and a zeroconf transport implementing NetworkDiscoveryHook.
  • Register the zeroconf transport as the default.
  • Resolve the backend's transport through the hook, so a registered override replaces zeroconf.
  • Keep zeroconf-specific concerns (interface/address monitoring, .local LocalHostnameListener) in the zeroconf transport.
  • Make NetworkDiscoveryBackend constructable and start/stoppable outside KolibriProcessBus.

Out of Scope

  • The Android NSD transport and service.
  • Changes to NetworkLocationListener / DynamicNetworkLocation / discovery-task behaviour.
  • The notification hooks (NetworkLocationDiscoveryHook / NetworkLocationBroadcastHook) — unchanged.

Acceptance Criteria

General

  • NetworkDiscoveryHook is a single-registration hook defining register, update, unregister, start_listening, stop_listening.
  • The zeroconf transport is extracted behind NetworkDiscoveryHook and registered as the default.
  • NetworkDiscoveryBackend resolves its transport through the hook, using a registered override instead of zeroconf.
  • NetworkDiscoveryBackend can be constructed and started/stopped without a KolibriProcessBus.
  • Discovered peers still produce DynamicNetworkLocation add/update/remove regardless of transport.
  • Server-platform broadcast and discovery via ZeroConfPlugin are unchanged.

Testing

  • Unit tests cover backend event dispatch to NetworkLocationListener with a fake transport, and transport resolution (default vs override).

References

  • KolibriBroadcast, build_broadcast_instancekolibri/core/discovery/utils/network/broadcast.py.
  • NetworkLocationListener, discovery tasks — kolibri/core/discovery/utils/network/search.py, kolibri/core/discovery/tasks.py.
  • ZeroConfPluginkolibri/utils/server/__init__.py.

AI usage

Drafted with Claude Code in an interactive design session. The author made every design decision in dialogue and verified the code references.

Metadata

Metadata

Assignees

Labels

DEV: backendPython, databases, networking, filesystem...TAG: tech update / debtChange not visible to userpythonPull requests that update Python code

Type

Fields

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions