vectorwave 0.1.8__tar.gz → 0.2.0__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 (82) hide show
  1. {vectorwave-0.1.8/src/vectorwave.egg-info → vectorwave-0.2.0}/PKG-INFO +46 -52
  2. {vectorwave-0.1.8 → vectorwave-0.2.0}/Readme.md +44 -50
  3. {vectorwave-0.1.8 → vectorwave-0.2.0}/pyproject.toml +2 -2
  4. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/core/test_semantic_caching.py +6 -3
  5. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/search/test_execution_search.py +23 -3
  6. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/utils/test_replayer.py +45 -1
  7. vectorwave-0.2.0/src/tests/utils/test_return_caching.py +126 -0
  8. vectorwave-0.2.0/src/tests/utils/test_status.py +126 -0
  9. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/__init__.py +7 -1
  10. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/db_search.py +107 -2
  11. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/models/db_config.py +4 -0
  12. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/factory.py +4 -2
  13. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/tracer.py +71 -7
  14. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/execution_search.py +2 -8
  15. vectorwave-0.2.0/src/vectorwave/utils/healer.py +155 -0
  16. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/utils/replayer.py +48 -12
  17. vectorwave-0.2.0/src/vectorwave/utils/replayer_semantic.py +232 -0
  18. vectorwave-0.2.0/src/vectorwave/utils/return_caching_utils.py +134 -0
  19. vectorwave-0.2.0/src/vectorwave/utils/status.py +55 -0
  20. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/factory.py +12 -10
  21. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/huggingface_vectorizer.py +6 -5
  22. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/openai_vectorizer.py +6 -5
  23. {vectorwave-0.1.8 → vectorwave-0.2.0/src/vectorwave.egg-info}/PKG-INFO +46 -52
  24. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/SOURCES.txt +5 -0
  25. vectorwave-0.1.8/src/vectorwave/utils/return_caching_utils.py +0 -76
  26. {vectorwave-0.1.8 → vectorwave-0.2.0}/LICENSE +0 -0
  27. {vectorwave-0.1.8 → vectorwave-0.2.0}/MANIFEST.in +0 -0
  28. {vectorwave-0.1.8 → vectorwave-0.2.0}/NOTICE +0 -0
  29. {vectorwave-0.1.8 → vectorwave-0.2.0}/setup.cfg +0 -0
  30. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/__init__.py +0 -0
  31. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/batch/__init__.py +0 -0
  32. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/batch/test_batch.py +0 -0
  33. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/conftest.py +0 -0
  34. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/core/__init__.py +0 -0
  35. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/core/test_decorator.py +0 -0
  36. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/__init__.py +0 -0
  37. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/test_archiver.py +0 -0
  38. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/test_db.py +0 -0
  39. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/test_db_search.py +0 -0
  40. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/exception/__init__.py +0 -0
  41. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/models/__init__.py +0 -0
  42. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/models/test_db_config.py +0 -0
  43. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/__init__.py +0 -0
  44. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/alert/__init__.py +0 -0
  45. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/alert/test_alerter.py +0 -0
  46. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/test_async_trace.py +0 -0
  47. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/test_tracer.py +0 -0
  48. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/prediction/__init__.py +0 -0
  49. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/search/__init__.py +0 -0
  50. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/utils/__init__.py +0 -0
  51. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/utils/test_function_cahe.py +0 -0
  52. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/vectorizer/__init__.py +0 -0
  53. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/batch/__init__.py +0 -0
  54. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/batch/batch.py +0 -0
  55. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/__init__.py +0 -0
  56. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/core.py +0 -0
  57. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/decorator.py +0 -0
  58. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/generator.py +0 -0
  59. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/__init__.py +0 -0
  60. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/archiver.py +0 -0
  61. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/db.py +0 -0
  62. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/exception/__init__.py +0 -0
  63. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/exception/exceptions.py +0 -0
  64. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/models/__init__.py +0 -0
  65. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/__init__.py +0 -0
  66. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/__init__.py +0 -0
  67. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/base.py +0 -0
  68. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/null_alerter.py +0 -0
  69. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/webhook_alerter.py +0 -0
  70. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/monitoring.py +0 -0
  71. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/prediction/__init__.py +0 -0
  72. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/prediction/predictor.py +0 -0
  73. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/__init__.py +0 -0
  74. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/extended_search.py +0 -0
  75. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/rag_search.py +0 -0
  76. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/utils/__init__.py +0 -0
  77. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/utils/function_cache.py +0 -0
  78. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/__init__.py +0 -0
  79. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/base.py +0 -0
  80. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/dependency_links.txt +0 -0
  81. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/requires.txt +0 -0
  82. {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectorwave
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: VectorWave: Seamless Auto-Vectorization Framework
5
5
  Author-email: junyeonggim <junyeonggim5@gmail.com>
6
6
  License-Expression: MIT
7
- Project-URL: Repository, https://github.com/republicofgamja/vtm
7
+ Project-URL: Repository, https://github.com/cozymori/vectorwave
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.10
10
10
  Classifier: Programming Language :: Python :: 3.11
@@ -130,62 +130,56 @@ process_payment("user_789", 5000)
130
130
 
131
131
  To use the LLM feature, you must specify dependencies and environment variables.
132
132
 
133
- > #### Prerequisites for AI Auto-Documentation
134
- >
135
- > To use the AI-powered documentation feature, you must have the `openai` library installed and configure your API key.
136
- >
137
- > 1. **Install Library:**
138
- >
139
- > ```bash
140
- > pip install openai
141
- > ```
142
- >
143
- > 2. **Set API Key:** Add your valid OpenAI API key to your `.env` file.
144
- >
145
- > ```text
146
- > OPENAI_API_KEY="sk-proj-YOUR_API_KEY_HERE"
147
- > # WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
148
- > ```
133
+ #### Prerequisites for AI Auto-Documentation
134
+
135
+ To use the AI-powered documentation feature, you must have the `openai` library installed and configure your API key.
136
+
137
+ 1. **Install Library:**
138
+ ```bash
139
+ pip install openai
140
+ ```
141
+
142
+ 2. **Set API Key:** Add your valid OpenAI API key to your `.env` file.
143
+ ```ini
144
+ OPENAI_API_KEY="sk-proj-YOUR_API_KEY_HERE"
145
+ # WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
146
+ ```
149
147
 
150
148
  ### 2.2. 🚀 Usage: Auto-Generating Function Metadata (Auto=True)
151
149
 
152
150
  Instead of manually defining `search_description` and `sequence_narrative`, you can use the `auto=True` flag.
153
151
 
154
- > #### 3\. Automatic Function Metadata Generation (Auto=True)
155
- >
156
- > You can use the `auto=True` flag instead of manually defining `search_description` and `sequence_narrative`.
157
- >
158
- > 1. **Mark Function:** Set `auto=True`. It is **strongly recommended to include a detailed Docstring** to enhance the LLM's analysis quality.
159
- >
160
- > ```python
161
- > # Code from vectorwave/test_ex/example.py
162
- > @vectorize(auto=True, team="loyalty-program")
163
- > def calculate_loyalty_points(purchase_amount: int, is_vip: bool):
164
- > """
165
- > Function to calculate loyalty points based on purchase amount.
166
- > VIP customers earn double points.
167
- > """
168
- > points = purchase_amount // 10
169
- > if is_vip:
170
- > points *= 2
171
- > return {"points": points, "tier": "VIP" if is_vip else "Regular"}
172
- > ```
173
- >
174
- > 2. **Trigger Generation:** Call `generate_and_register_metadata()` **immediately after** all `@vectorize` function definitions are complete. This function calls the LLM, vectorizes the generated metadata, and registers it to the DB.
175
- >
176
- > ```python
177
- > # ... (After defining the calculate_loyalty_points function above)
178
- > ```
179
-
180
- > ````
181
- > # [Mandatory] Must be called after all function definitions are complete.
182
- > print("🚀 Checking for functions needing auto-documentation...")
183
- > generate_and_register_metadata()
184
- > ```
185
- > ````
186
- >
187
- > *Note: Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.*
152
+ #### 3. Automatic Function Metadata Generation (Auto=True)
153
+
154
+ You can use the `auto=True` flag instead of manually defining `search_description` and `sequence_narrative`.
155
+
156
+ 1. **Mark Function:** Set `auto=True`. It is **strongly recommended to include a detailed Docstring** to enhance the LLM's analysis quality.
157
+
158
+ ```python
159
+ # Code from vectorwave/test_ex/example.py
160
+ @vectorize(auto=True, team="loyalty-program")
161
+ def calculate_loyalty_points(purchase_amount: int, is_vip: bool):
162
+ """
163
+ Function to calculate loyalty points based on purchase amount.
164
+ VIP customers earn double points.
165
+ """
166
+ points = purchase_amount // 10
167
+ if is_vip:
168
+ points *= 2
169
+ return {"points": points, "tier": "VIP" if is_vip else "Regular"}
170
+ ```
171
+
172
+ 2. **Trigger Generation:** Call `generate_and_register_metadata()` **immediately after** all `@vectorize` function definitions are complete. This function calls the LLM, vectorizes the generated metadata, and registers it to the DB.
173
+
174
+ ```python
175
+ # ... (After defining the calculate_loyalty_points function above)
176
+
177
+ # [Mandatory] Must be called after all function definitions are complete.
178
+ print("🚀 Checking for functions needing auto-documentation...")
179
+ generate_and_register_metadata()
180
+ ```
188
181
 
182
+ > **Note:** Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.
189
183
  -----
190
184
 
191
185
  #### Semantic Caching Example
@@ -104,62 +104,56 @@ process_payment("user_789", 5000)
104
104
 
105
105
  To use the LLM feature, you must specify dependencies and environment variables.
106
106
 
107
- > #### Prerequisites for AI Auto-Documentation
108
- >
109
- > To use the AI-powered documentation feature, you must have the `openai` library installed and configure your API key.
110
- >
111
- > 1. **Install Library:**
112
- >
113
- > ```bash
114
- > pip install openai
115
- > ```
116
- >
117
- > 2. **Set API Key:** Add your valid OpenAI API key to your `.env` file.
118
- >
119
- > ```text
120
- > OPENAI_API_KEY="sk-proj-YOUR_API_KEY_HERE"
121
- > # WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
122
- > ```
107
+ #### Prerequisites for AI Auto-Documentation
108
+
109
+ To use the AI-powered documentation feature, you must have the `openai` library installed and configure your API key.
110
+
111
+ 1. **Install Library:**
112
+ ```bash
113
+ pip install openai
114
+ ```
115
+
116
+ 2. **Set API Key:** Add your valid OpenAI API key to your `.env` file.
117
+ ```ini
118
+ OPENAI_API_KEY="sk-proj-YOUR_API_KEY_HERE"
119
+ # WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
120
+ ```
123
121
 
124
122
  ### 2.2. 🚀 Usage: Auto-Generating Function Metadata (Auto=True)
125
123
 
126
124
  Instead of manually defining `search_description` and `sequence_narrative`, you can use the `auto=True` flag.
127
125
 
128
- > #### 3\. Automatic Function Metadata Generation (Auto=True)
129
- >
130
- > You can use the `auto=True` flag instead of manually defining `search_description` and `sequence_narrative`.
131
- >
132
- > 1. **Mark Function:** Set `auto=True`. It is **strongly recommended to include a detailed Docstring** to enhance the LLM's analysis quality.
133
- >
134
- > ```python
135
- > # Code from vectorwave/test_ex/example.py
136
- > @vectorize(auto=True, team="loyalty-program")
137
- > def calculate_loyalty_points(purchase_amount: int, is_vip: bool):
138
- > """
139
- > Function to calculate loyalty points based on purchase amount.
140
- > VIP customers earn double points.
141
- > """
142
- > points = purchase_amount // 10
143
- > if is_vip:
144
- > points *= 2
145
- > return {"points": points, "tier": "VIP" if is_vip else "Regular"}
146
- > ```
147
- >
148
- > 2. **Trigger Generation:** Call `generate_and_register_metadata()` **immediately after** all `@vectorize` function definitions are complete. This function calls the LLM, vectorizes the generated metadata, and registers it to the DB.
149
- >
150
- > ```python
151
- > # ... (After defining the calculate_loyalty_points function above)
152
- > ```
153
-
154
- > ````
155
- > # [Mandatory] Must be called after all function definitions are complete.
156
- > print("🚀 Checking for functions needing auto-documentation...")
157
- > generate_and_register_metadata()
158
- > ```
159
- > ````
160
- >
161
- > *Note: Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.*
126
+ #### 3. Automatic Function Metadata Generation (Auto=True)
127
+
128
+ You can use the `auto=True` flag instead of manually defining `search_description` and `sequence_narrative`.
129
+
130
+ 1. **Mark Function:** Set `auto=True`. It is **strongly recommended to include a detailed Docstring** to enhance the LLM's analysis quality.
131
+
132
+ ```python
133
+ # Code from vectorwave/test_ex/example.py
134
+ @vectorize(auto=True, team="loyalty-program")
135
+ def calculate_loyalty_points(purchase_amount: int, is_vip: bool):
136
+ """
137
+ Function to calculate loyalty points based on purchase amount.
138
+ VIP customers earn double points.
139
+ """
140
+ points = purchase_amount // 10
141
+ if is_vip:
142
+ points *= 2
143
+ return {"points": points, "tier": "VIP" if is_vip else "Regular"}
144
+ ```
145
+
146
+ 2. **Trigger Generation:** Call `generate_and_register_metadata()` **immediately after** all `@vectorize` function definitions are complete. This function calls the LLM, vectorizes the generated metadata, and registers it to the DB.
147
+
148
+ ```python
149
+ # ... (After defining the calculate_loyalty_points function above)
150
+
151
+ # [Mandatory] Must be called after all function definitions are complete.
152
+ print("🚀 Checking for functions needing auto-documentation...")
153
+ generate_and_register_metadata()
154
+ ```
162
155
 
156
+ > **Note:** Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.
163
157
  -----
164
158
 
165
159
  #### Semantic Caching Example
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vectorwave"
7
- version = "0.1.8"
7
+ version = "0.2.0"
8
8
  authors = [
9
9
  { name = "junyeonggim", email = "junyeonggim5@gmail.com" },
10
10
  ]
@@ -32,7 +32,7 @@ dependencies = [
32
32
  ]
33
33
 
34
34
  [project.urls]
35
- Repository = "https://github.com/republicofgamja/vtm"
35
+ Repository = "https://github.com/cozymori/vectorwave"
36
36
 
37
37
  [tool.setuptools.packages.find]
38
38
  where = ["src"]
@@ -14,6 +14,8 @@ from vectorwave.batch.batch import get_batch_manager as real_get_batch_manager
14
14
  from vectorwave.database.db import get_cached_client as real_get_cached_client
15
15
  from vectorwave.models.db_config import get_weaviate_settings as real_get_settings
16
16
  from vectorwave.vectorizer.factory import get_vectorizer as real_get_vectorizer
17
+ from vectorwave.monitoring.tracer import _create_input_vector_data
18
+
17
19
 
18
20
  # --- Fixture Setup ---
19
21
 
@@ -326,7 +328,6 @@ def test_tracer_input_vector_data_and_masking(mock_caching_deps):
326
328
  """
327
329
  Tests that the _create_input_vector_data function masks sensitive keys.
328
330
  """
329
- from vectorwave.monitoring.tracer import _create_input_vector_data
330
331
 
331
332
  # Arrange: settings has sensitive_keys={"secret_key"}
332
333
  settings = mock_caching_deps["settings"]
@@ -343,10 +344,12 @@ def test_tracer_input_vector_data_and_masking(mock_caching_deps):
343
344
  text_content = input_data["text"]
344
345
  assert "test_func" in text_content
345
346
  assert "amount" in text_content
346
- assert "[MASKED]" in text_content
347
+
348
+ assert "[MASKED]" not in text_content
349
+ assert "secret_key" not in text_content
347
350
  assert "my_top_secret" not in text_content
348
351
 
349
- # 2. Verification: Check if masking is included in the properties dictionary
352
+ # 2. Verification: Check stored properties
350
353
  props = input_data["properties"]
351
354
  assert props["function"] == "test_func"
352
355
  assert props["kwargs"]["amount"] == 100
@@ -54,7 +54,6 @@ mock_db_errors = [
54
54
  {"timestamp_utc": (mock_now - timedelta(minutes=15)).isoformat(), "error_code": "INVALID_INPUT"}, # Too old
55
55
  ]
56
56
 
57
-
58
57
  # [Core Fix] Create mock datetime class
59
58
  # Replaces the datetime.datetime class itself.
60
59
  MockDateTime = MagicMock()
@@ -80,10 +79,31 @@ def test_find_recent_errors(mock_find_executions):
80
79
  filters_arg = call_args.kwargs['filters']
81
80
 
82
81
  assert filters_arg['status'] == 'ERROR'
83
- assert filters_arg['error_code'] == 'INVALID_INPUT'
82
+ assert filters_arg['error_code'] == ['INVALID_INPUT']
84
83
  assert filters_arg['timestamp_utc__gte'] == expected_time_limit_iso
85
84
 
86
85
 
86
+ @patch('vectorwave.search.execution_search.datetime', MockDateTime)
87
+ @patch('vectorwave.search.execution_search.find_executions')
88
+ def test_find_recent_errors_multi_code(mock_find_executions):
89
+ """
90
+ Tests if find_recent_errors handles multiple error codes correctly by passing the list.
91
+ (Tests the newly implemented multi-code filtering path)
92
+ """
93
+ error_list = ["INVALID_INPUT", "TIMEOUT_ERROR"]
94
+ find_recent_errors(minutes_ago=20, limit=5, error_codes=error_list)
95
+
96
+ call_args = mock_find_executions.call_args
97
+ filters_arg = call_args.kwargs['filters']
98
+
99
+ assert filters_arg['status'] == 'ERROR'
100
+ assert filters_arg['error_code'] == error_list
101
+ assert call_args.kwargs['limit'] == 5
102
+
103
+ expected_time_limit_iso_20 = (mock_now - timedelta(minutes=20)).isoformat()
104
+ assert filters_arg['timestamp_utc__gte'] == expected_time_limit_iso_20
105
+
106
+
87
107
  @patch('vectorwave.search.execution_search.find_executions')
88
108
  def test_find_slowest_executions(mock_find_executions):
89
109
  """
@@ -122,4 +142,4 @@ def test_find_by_trace_id(mock_find_executions):
122
142
  # 2. Verify sort order (time ascending)
123
143
  assert call_args.kwargs['sort_by'] == 'timestamp_utc'
124
144
  assert call_args.kwargs['sort_ascending'] == True
125
- assert call_args.kwargs['limit'] == 100
145
+ assert call_args.kwargs['limit'] == 100
@@ -1,5 +1,7 @@
1
1
  import pytest
2
2
  import json
3
+ import asyncio
4
+ import inspect
3
5
  from unittest.mock import MagicMock, patch
4
6
  from vectorwave.utils.replayer import VectorWaveReplayer
5
7
 
@@ -194,4 +196,46 @@ def test_replay_argument_filtering(mock_replayer_deps):
194
196
 
195
197
  # Assert
196
198
  # Should only be called with 'a=10', excluding 'team' and 'priority'
197
- mock_func.assert_called_once_with(a=10)
199
+ mock_func.assert_called_once_with(a=10)
200
+
201
+ def test_replay_async_function_execution_fixed(mock_replayer_deps):
202
+ """
203
+ [Case 5] Async Function Test (FIXED): Tests the async execution path using patching
204
+ of the import mechanism and executing the actual async function via asyncio.run.
205
+ """
206
+ # Arrange
207
+ replayer = VectorWaveReplayer()
208
+
209
+ # 1. DB Mock Data
210
+ inputs = {"a": 1, "b": 2}
211
+ expected_result = 3
212
+ mock_logs = [create_mock_log("uuid-async-1", inputs, expected_result)]
213
+ mock_replayer_deps["query"].fetch_objects.return_value.objects = mock_logs
214
+
215
+ # 2. Define the actual ASYNC function for replayer to execute
216
+ async def real_async_add(a, b):
217
+ # This function will be called and executed by asyncio.run
218
+ await asyncio.sleep(0.001)
219
+ return a + b
220
+
221
+ # Manually attach the signature for the replayer's inspection check to pass
222
+ setattr(real_async_add, '__signature__', inspect.Signature([
223
+ inspect.Parameter('a', inspect.Parameter.POSITIONAL_OR_KEYWORD),
224
+ inspect.Parameter('b', inspect.Parameter.POSITIONAL_OR_KEYWORD)
225
+ ]))
226
+
227
+ # 3. Patch importlib.import_module to return a mock module that contains the target function
228
+ mock_module = MagicMock()
229
+ mock_module.async_add = real_async_add # The mock module must have the function
230
+
231
+ with patch("vectorwave.utils.replayer.importlib.import_module", return_value=mock_module):
232
+
233
+ # Act
234
+ # replayer.replay (sync function) calls asyncio.run(real_async_add(**inputs)) internally.
235
+ result = replayer.replay("my_module.async_add", limit=1)
236
+
237
+ # Assert
238
+ # 1. The result should be successful and match the expected output
239
+ assert result["passed"] == 1
240
+ assert result["failed"] == 0
241
+ assert result["failures"] == []
@@ -0,0 +1,126 @@
1
+ import pytest
2
+ from unittest.mock import MagicMock, patch
3
+ import json
4
+ from vectorwave.utils.return_caching_utils import _check_and_return_cached_result
5
+ from vectorwave.models.db_config import WeaviateSettings
6
+
7
+
8
+ # --- Mock Fixtures ---
9
+
10
+ @pytest.fixture
11
+ def mock_caching_utils_deps(monkeypatch):
12
+ """
13
+ Mocks external dependencies of return_caching_utils.py (BatchManager, Tracer, DB search, etc.).
14
+ """
15
+ # 1. Mock Settings
16
+ mock_settings = WeaviateSettings(
17
+ EXECUTION_COLLECTION_NAME="TestExecutions",
18
+ global_custom_values={"run_id": "test-run-123"}
19
+ )
20
+ mock_get_settings = MagicMock(return_value=mock_settings)
21
+
22
+ # 2. Mock Batch Manager (Key verification target)
23
+ mock_batch_manager = MagicMock()
24
+ mock_batch_manager.add_object = MagicMock()
25
+ mock_get_batch = MagicMock(return_value=mock_batch_manager)
26
+
27
+ # 3. Mock Vectorizer
28
+ mock_vectorizer = MagicMock()
29
+ mock_vectorizer.embed.return_value = [0.1, 0.2, 0.3] # Dummy Vector
30
+ mock_get_vectorizer = MagicMock(return_value=mock_vectorizer)
31
+
32
+ # 4. Mock Tracer Context (Provides current Trace ID)
33
+ mock_tracer = MagicMock()
34
+ mock_tracer.trace_id = "existing-trace-id-abc"
35
+
36
+ # 5. Apply Monkeypatches
37
+ TARGET_MODULE = "vectorwave.utils.return_caching_utils"
38
+
39
+ monkeypatch.setattr(f"{TARGET_MODULE}.get_weaviate_settings", mock_get_settings)
40
+ monkeypatch.setattr(f"{TARGET_MODULE}.get_batch_manager", mock_get_batch)
41
+ monkeypatch.setattr(f"{TARGET_MODULE}.get_vectorizer", mock_get_vectorizer)
42
+
43
+ return {
44
+ "batch_manager": mock_batch_manager,
45
+ "vectorizer": mock_vectorizer,
46
+ "tracer_obj": mock_tracer
47
+ }
48
+
49
+
50
+ def test_check_and_return_cached_result_cache_hit_logging(mock_caching_utils_deps):
51
+ """
52
+ [Case 1] Verify that DB logging is correctly performed with 'CACHE_HIT' status upon a cache hit.
53
+ """
54
+ # Arrange
55
+ # 1. Mock cache search result (Log found in DB)
56
+ mock_cached_log = {
57
+ "return_value": json.dumps({"result": "cached_data"}),
58
+ "metadata": {"distance": 0.1},
59
+ "uuid": "cached-log-uuid"
60
+ }
61
+
62
+ # 2. Mock search_similar_execution to return the above result (Simulate Cache Hit)
63
+ with patch("vectorwave.utils.return_caching_utils.search_similar_execution", return_value=mock_cached_log):
64
+ # [Fix] Instead of directly patching the .get method of the ContextVar object, replace the variable itself with a Mock object.
65
+ with patch("vectorwave.utils.return_caching_utils.current_tracer_var") as mock_tracer_var:
66
+ with patch("vectorwave.utils.return_caching_utils.current_span_id_var") as mock_span_var:
67
+ # Set return value for .get() call on the Mock object
68
+ mock_tracer_var.get.return_value = mock_caching_utils_deps["tracer_obj"]
69
+ mock_span_var.get.return_value = "parent-span-123"
70
+
71
+ # 4. Execute the target function
72
+ def dummy_func(a, b): pass # Target function
73
+
74
+ result = _check_and_return_cached_result(
75
+ func=dummy_func,
76
+ args=(10,),
77
+ kwargs={"b": 20},
78
+ function_name="dummy_func",
79
+ cache_threshold=0.9,
80
+ is_async=False
81
+ )
82
+
83
+ # Assert
84
+ # 1. Was the cached result returned correctly?
85
+ assert result == {"result": "cached_data"}
86
+
87
+ # 2. [Core] Was BatchManager.add_object called? (Check if logging occurred)
88
+ mock_batch = mock_caching_utils_deps["batch_manager"]
89
+ mock_batch.add_object.assert_called_once()
90
+
91
+ # 3. [Core] Verify properties of the saved log
92
+ call_kwargs = mock_batch.add_object.call_args.kwargs
93
+ props = call_kwargs["properties"]
94
+
95
+ assert props["status"] == "CACHE_HIT" # Check if status is CACHE_HIT
96
+ assert props["duration_ms"] == 0.0 # Check if duration is 0
97
+ assert props["trace_id"] == "existing-trace-id-abc" # Check if existing Trace ID is maintained
98
+ assert props["parent_span_id"] == "parent-span-123" # Check for parent Span ID maintenance
99
+ assert props["function_name"] == "dummy_func"
100
+ assert props["run_id"] == "test-run-123" # Check for inclusion of global tags
101
+
102
+
103
+ def test_check_and_return_cached_result_cache_miss(mock_caching_utils_deps):
104
+ """
105
+ [Case 2] Verify that None is returned without logging upon a cache miss.
106
+ """
107
+ # Arrange
108
+ # Set search_similar_execution to return None (Cache Miss)
109
+ with patch("vectorwave.utils.return_caching_utils.search_similar_execution", return_value=None):
110
+ def dummy_func(): pass
111
+
112
+ result = _check_and_return_cached_result(
113
+ func=dummy_func,
114
+ args=(),
115
+ kwargs={},
116
+ function_name="dummy_func",
117
+ cache_threshold=0.9,
118
+ is_async=False
119
+ )
120
+
121
+ # Assert
122
+ # 1. Result should be None (To proceed to actual function execution)
123
+ assert result is None
124
+
125
+ # 2. BatchManager.add_object should not be called
126
+ mock_caching_utils_deps["batch_manager"].add_object.assert_not_called()
@@ -0,0 +1,126 @@
1
+ import pytest
2
+ from unittest.mock import MagicMock, patch
3
+ from vectorwave.utils.status import get_db_status, get_registered_functions
4
+ from vectorwave.models.db_config import WeaviateSettings
5
+
6
+ # --- Fixtures ---
7
+
8
+ @pytest.fixture
9
+ def mock_status_deps(monkeypatch):
10
+ """
11
+ Mocks dependencies of status.py (get_cached_client, get_weaviate_settings).
12
+ """
13
+ # 1. Mock Weaviate Client
14
+ mock_client = MagicMock()
15
+ mock_get_client = MagicMock(return_value=mock_client)
16
+
17
+ # 2. Mock Settings
18
+ mock_settings = WeaviateSettings(COLLECTION_NAME="TestFunctions")
19
+ mock_get_settings = MagicMock(return_value=mock_settings)
20
+
21
+ # 3. Apply Patches
22
+ monkeypatch.setattr("vectorwave.utils.status.get_cached_client", mock_get_client)
23
+ monkeypatch.setattr("vectorwave.utils.status.get_weaviate_settings", mock_get_settings)
24
+
25
+ return {
26
+ "client": mock_client,
27
+ "settings": mock_settings,
28
+ "get_client": mock_get_client
29
+ }
30
+
31
+ # --- Tests for get_db_status ---
32
+
33
+ def test_get_db_status_ready(mock_status_deps):
34
+ """
35
+ Case 1: Test if True is returned when DB is connected and ready.
36
+ """
37
+ mock_status_deps["client"].is_ready.return_value = True
38
+
39
+ assert get_db_status() is True
40
+ mock_status_deps["client"].is_ready.assert_called_once()
41
+
42
+ def test_get_db_status_not_ready(mock_status_deps):
43
+ """
44
+ Case 2: Test if False is returned when DB is connected but not ready.
45
+ """
46
+ mock_status_deps["client"].is_ready.return_value = False
47
+
48
+ assert get_db_status() is False
49
+
50
+ def test_get_db_status_exception(mock_status_deps):
51
+ """
52
+ Case 3: Test if False is returned and error is logged when an exception occurs during DB connection.
53
+ """
54
+ # Set exception to occur on client call
55
+ mock_status_deps["get_client"].side_effect = Exception("Connection Error")
56
+
57
+ assert get_db_status() is False
58
+
59
+ # --- Tests for get_registered_functions ---
60
+
61
+ @patch("vectorwave.utils.status.get_db_status")
62
+ def test_get_registered_functions_db_offline(mock_get_db_status, mock_status_deps):
63
+ """
64
+ Case 4: Test if an empty list is returned when DB is offline (False).
65
+ """
66
+ mock_get_db_status.return_value = False
67
+
68
+ result = get_registered_functions()
69
+
70
+ assert result == []
71
+ # Should not access client or collection if DB is offline
72
+ mock_status_deps["client"].collections.get.assert_not_called()
73
+
74
+ @patch("vectorwave.utils.status.get_db_status")
75
+ def test_get_registered_functions_success(mock_get_db_status, mock_status_deps):
76
+ """
77
+ Case 5: Test if the list of registered functions is returned correctly.
78
+ """
79
+ # 1. Arrange
80
+ mock_get_db_status.return_value = True
81
+
82
+ # Mock collection and query results
83
+ mock_collection = MagicMock()
84
+ mock_status_deps["client"].collections.get.return_value = mock_collection
85
+
86
+ # Create fake Weaviate objects
87
+ obj1 = MagicMock()
88
+ obj1.properties = {"function_name": "func_a", "module_name": "mod_a"}
89
+ obj2 = MagicMock()
90
+ obj2.properties = {"function_name": "func_b", "module_name": "mod_b"}
91
+
92
+ # Mock result of fetch_objects call
93
+ mock_collection.iterator.return_value = [obj1, obj2]
94
+
95
+ # 2. Act
96
+ result = get_registered_functions()
97
+
98
+ # 3. Assert
99
+ assert len(result) == 2
100
+ assert result[0]["function_name"] == "func_a"
101
+ assert result[1]["function_name"] == "func_b"
102
+
103
+ # Verify correct name usage when retrieving collection
104
+ mock_status_deps["client"].collections.get.assert_called_with("TestFunctions")
105
+
106
+ mock_collection.iterator.assert_called_once()
107
+ call_kwargs = mock_collection.iterator.call_args.kwargs
108
+ assert "return_properties" in call_kwargs
109
+ assert "function_name" in call_kwargs["return_properties"]
110
+
111
+ @patch("vectorwave.utils.status.get_db_status")
112
+ def test_get_registered_functions_exception(mock_get_db_status, mock_status_deps):
113
+ """
114
+ Case 6: Test if an empty list is returned and error is handled when an exception occurs during retrieval.
115
+ """
116
+ # 1. Arrange
117
+ mock_get_db_status.return_value = True
118
+
119
+ # Induce exception during collection retrieval
120
+ mock_status_deps["client"].collections.get.side_effect = Exception("Query Failed")
121
+
122
+ # 2. Act
123
+ result = get_registered_functions()
124
+
125
+ # 3. Assert
126
+ assert result == []
@@ -5,6 +5,9 @@ from .database.db_search import search_functions, search_executions, search_erro
5
5
  from .monitoring.tracer import trace_span
6
6
  from .search.rag_search import search_and_answer, analyze_trace_log
7
7
  from .core.generator import generate_and_register_metadata
8
+ from .utils.healer import VectorWaveHealer
9
+ from .utils.replayer import VectorWaveReplayer
10
+ from .utils.replayer_semantic import SemanticReplayer
8
11
 
9
12
  __all__ = [
10
13
  'vectorize',
@@ -16,5 +19,8 @@ __all__ = [
16
19
  'trace_span',
17
20
  'search_and_answer',
18
21
  'analyze_trace_log',
19
- 'generate_and_register_metadata'
22
+ 'generate_and_register_metadata',
23
+ 'VectorWaveHealer',
24
+ 'VectorWaveReplayer',
25
+ 'SemanticReplayer'
20
26
  ]