synap-git 2.1.1__tar.gz → 2.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {synap_git-2.1.1 → synap_git-2.1.2}/CHANGELOG.md +6 -0
  2. {synap_git-2.1.1 → synap_git-2.1.2}/PKG-INFO +1 -1
  3. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/__init__.py +1 -1
  4. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/indexer/daemon.py +1 -0
  5. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/indexer/engine.py +12 -9
  6. {synap_git-2.1.1 → synap_git-2.1.2}/.gitignore +0 -0
  7. {synap_git-2.1.1 → synap_git-2.1.2}/.synap.example/README.md +0 -0
  8. {synap_git-2.1.1 → synap_git-2.1.2}/LICENSE.md +0 -0
  9. {synap_git-2.1.1 → synap_git-2.1.2}/README.md +0 -0
  10. {synap_git-2.1.1 → synap_git-2.1.2}/pyproject.toml +0 -0
  11. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/api/__init__.py +0 -0
  12. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/api/app.py +0 -0
  13. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/api/static/index.html +0 -0
  14. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/cli/__init__.py +0 -0
  15. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/cli/__main__.py +0 -0
  16. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/cli/main.py +0 -0
  17. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/config.py +0 -0
  18. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/diagnostics/__init__.py +0 -0
  19. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/diagnostics/logger.py +0 -0
  20. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/diagnostics/tracing.py +0 -0
  21. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/embeddings/__init__.py +0 -0
  22. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/git/__init__.py +0 -0
  23. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/git/state.py +0 -0
  24. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/indexer/__init__.py +0 -0
  25. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/indexer/scanner.py +0 -0
  26. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/indexer/wiki.py +0 -0
  27. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/mcp/__init__.py +0 -0
  28. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/mcp/server.py +0 -0
  29. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/parser/__init__.py +0 -0
  30. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/parser/registry.py +0 -0
  31. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/anthropic.py +0 -0
  32. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/base.py +0 -0
  33. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/factory.py +0 -0
  34. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/gemini.py +0 -0
  35. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/ollama.py +0 -0
  36. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/openai.py +0 -0
  37. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/provider/openrouter.py +0 -0
  38. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/py.typed +0 -0
  39. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/retrieval/__init__.py +0 -0
  40. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/retrieval/engine.py +0 -0
  41. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/retrieval/memory.py +0 -0
  42. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/storage/__init__.py +0 -0
  43. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/storage/sqlite.py +0 -0
  44. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/utils/__init__.py +0 -0
  45. {synap_git-2.1.1 → synap_git-2.1.2}/src/synap_git/utils/serialization.py +0 -0
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.2] - 2026-06-11
9
+
10
+ ### Fixed
11
+ - **CRITICAL: Daemon Thread Explosion**: Patched a massive concurrency edge case in `SynapRuntime` where large repository indexing would trigger unbounded `threading.Thread` loops for LLM embeddings. A bounded `ThreadPoolExecutor` has been introduced to prevent OOMs, OS thread starvation, and rate-limit hits during first-run indexing.
12
+ - **Daemon Lifecycle**: Ensure `embedding_executor` shuts down cleanly without leaking background threads when the daemon loop receives SIGTERM.
13
+
8
14
  ## [2.1.1] - 2026-06-11
9
15
 
10
16
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synap-git
3
- Version: 2.1.1
3
+ Version: 2.1.2
4
4
  Summary: Persistent structural context infrastructure for AI coding agents.
5
5
  Project-URL: Homepage, https://github.com/saahilpal/synap-git
6
6
  Project-URL: Repository, https://github.com/saahilpal/synap-git
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "2.1.1"
5
+ __version__ = "2.1.2"
@@ -123,6 +123,7 @@ class RuntimeDaemon:
123
123
  except (asyncio.CancelledError, Exception):
124
124
  pass
125
125
 
126
+ self.runtime.shutdown()
126
127
  self._delete_heartbeat()
127
128
  self.logger.info("daemon_stopped")
128
129
 
@@ -81,6 +81,17 @@ class SynapRuntime:
81
81
  self.wiki = WikiEngine(settings, self.store)
82
82
  self.commit_count = 0
83
83
 
84
+ import concurrent.futures
85
+
86
+ self.embedding_executor = concurrent.futures.ThreadPoolExecutor(
87
+ max_workers=5, thread_name_prefix="embed_worker"
88
+ )
89
+
90
+ def shutdown(self) -> None:
91
+ """Gracefully shutdown background tasks and executors."""
92
+ self.logger.info("shutting_down_embedding_executor")
93
+ self.embedding_executor.shutdown(wait=False)
94
+
84
95
  def initialize_storage(self, *, auto_recover: bool = True) -> None:
85
96
  self.settings.ensure_directories()
86
97
  if auto_recover and self.store.path.exists() and self.store.recover_if_corrupted():
@@ -284,15 +295,7 @@ class SynapRuntime:
284
295
  except Exception as e:
285
296
  logger.warning("background_embed_failed", error=str(e))
286
297
 
287
- try:
288
- import asyncio
289
-
290
- loop = asyncio.get_running_loop()
291
- loop.create_task(asyncio.to_thread(_worker))
292
- except RuntimeError:
293
- import threading
294
-
295
- threading.Thread(target=_worker, daemon=True).start()
298
+ self.embedding_executor.submit(_worker)
296
299
 
297
300
  def _first_run_index(self, git_state: GitState) -> str | None:
298
301
  self.logger.info("first_run_indexing_started", branch=git_state.effective_branch)
File without changes
File without changes
File without changes
File without changes