diff --git a/CHANGELOG.md b/CHANGELOG.md index bce7384..4958d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.1] - 2026-04-05 + +### Fixed +- **3 bugs found by live broker testing:** + - `cache keys`: sync/async mismatch — `cacher.keys()` is sync + - `destroy`: use `registry.__services__` fallback (broker has no `destroyService` yet) + - `load`: use `broker.register()` (broker has no `addLocalService`) + ## [0.3.0] - 2026-04-05 ### Added diff --git a/pyproject.toml b/pyproject.toml index ca9ca81..592d852 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "moleculerpy-repl" -version = "0.3.0" +version = "0.3.1" description = "Interactive CLI shell for MoleculerPy microservices framework" readme = "README.md" license = "MIT" diff --git a/src/moleculerpy_repl/commands/cache.py b/src/moleculerpy_repl/commands/cache.py index 82fcdba..16bd457 100644 --- a/src/moleculerpy_repl/commands/cache.py +++ b/src/moleculerpy_repl/commands/cache.py @@ -39,7 +39,10 @@ async def _list_keys(self, cacher: Any, args: ParsedArgs) -> CommandResult: try: if hasattr(cacher, "keys"): - keys = await cacher.keys(pattern) if pattern else await cacher.keys() + raw_keys = cacher.keys(pattern) if pattern else cacher.keys() + # keys() may be sync or async depending on cacher impl + import asyncio + keys = (await raw_keys) if asyncio.iscoroutine(raw_keys) else raw_keys else: return CommandResult( success=False, diff --git a/src/moleculerpy_repl/commands/destroy.py b/src/moleculerpy_repl/commands/destroy.py index f1c768f..bd0bd61 100644 --- a/src/moleculerpy_repl/commands/destroy.py +++ b/src/moleculerpy_repl/commands/destroy.py @@ -26,34 +26,40 @@ async def execute(self, broker: Any, args: ParsedArgs) -> CommandResult: service_name = args.positional[0] try: + # Try broker.destroyService first (Node.js pattern) if hasattr(broker, "destroyService"): - # Find the service instance by name service = None if hasattr(broker, "services"): service = broker.services.get(service_name) - + if service is None and hasattr(broker, "registry"): + service = broker.registry.__services__.get(service_name) if service is None: return CommandResult(success=False, error=f"Service '{service_name}' not found") - await broker.destroyService(service) - return CommandResult( - success=True, - output=f"Service '{service_name}' destroyed.", - ) + elif hasattr(broker, "registry"): + # Fallback: remove from registry directly + registry = broker.registry + if service_name not in registry.__services__: + return CommandResult(success=False, error=f"Service '{service_name}' not found") + del registry.__services__[service_name] + # Remove associated actions + registry.__actions__ = [a for a in registry.__actions__ if not a.name.startswith(f"{service_name}.")] + registry._actions_by_name = { + k: v for k, v in registry._actions_by_name.items() + if not k.startswith(f"{service_name}.") + } else: - return CommandResult( - success=False, - error="broker.destroyService is not supported in this version", - ) + return CommandResult(success=False, error="Cannot destroy: no registry access") + return CommandResult(success=True, output=f"Service '{service_name}' destroyed.") except Exception as e: return CommandResult(success=False, error=f"Destroy failed: {e}") def get_completions(self, broker: Any, text: str, line: str) -> list[str]: """Get service name completions.""" try: - if hasattr(broker, "services"): - return [name for name in broker.services if name.startswith(text)] + if hasattr(broker, "registry"): + return [n for n in broker.registry.__services__ if n.startswith(text)] except Exception: pass return [] diff --git a/src/moleculerpy_repl/commands/load.py b/src/moleculerpy_repl/commands/load.py index 09654ac..7780205 100644 --- a/src/moleculerpy_repl/commands/load.py +++ b/src/moleculerpy_repl/commands/load.py @@ -70,8 +70,14 @@ async def execute(self, broker: Any, args: ParsedArgs) -> CommandResult: error=f"No Service subclass found in {file_path.name}", ) - svc = service_class(broker) - await broker.addLocalService(svc) + svc = service_class() + # Use broker.register() — the standard MoleculerPy API + if hasattr(broker, "register"): + await broker.register(svc) + elif hasattr(broker, "addLocalService"): + await broker.addLocalService(svc) + else: + return CommandResult(success=False, error="Cannot register service: no register method") return CommandResult( success=True,