@@ -87,7 +87,8 @@ class CustomMilvusContainer(MilvusContainer):
8787 Extends MilvusContainer to provide custom port binding and environment
8888 configuration for testing with standalone Milvus instances.
8989 """
90- def __init__ (
90+
91+ def __init__ ( # pylint: disable=bad-super-call
9192 self ,
9293 image : str ,
9394 service_container_port ,
@@ -96,7 +97,11 @@ def __init__(
9697 ) -> None :
9798 # Skip the parent class's constructor and go straight to
9899 # GenericContainer.
99- super (MilvusContainer , self ).__init__ (image = image , ** kwargs )
100+ super (
101+ MilvusContainer ,
102+ self ,
103+ ).__init__ (
104+ image = image , ** kwargs )
100105 self .port = service_container_port
101106 self .healthcheck_port = healthcheck_container_port
102107 self .with_exposed_ports (service_container_port , healthcheck_container_port )
@@ -133,6 +138,27 @@ class MilvusTestHelpers:
133138 # https://milvus.io/docs/release_notes.md or PyPI at
134139 # https://pypi.org/project/pymilvus/ for version compatibility.
135140 # Example: Milvus v2.6.0 requires pymilvus==2.6.0 (exact match required).
141+ @staticmethod
142+ def _wait_for_milvus_grpc (uri : str ) -> None :
143+ """Wait until Milvus accepts RPCs.
144+
145+ Docker may report started before gRPC is ready.
146+ """
147+ def list_collections_probe ():
148+ client = MilvusClient (uri = uri )
149+ try :
150+ client .list_collections ()
151+ finally :
152+ client .close ()
153+
154+ retry_with_backoff (
155+ list_collections_probe ,
156+ max_retries = 25 ,
157+ retry_delay = 2.0 ,
158+ retry_backoff_factor = 1.2 ,
159+ operation_name = "Milvus client connection after container start" ,
160+ exception_types = (MilvusException , ))
161+
136162 @staticmethod
137163 def start_db_container (
138164 image = "milvusdb/milvus:v2.5.10" ,
@@ -148,23 +174,31 @@ def start_db_container(
148174 if tc_max_retries is not None :
149175 testcontainers_config .max_tries = tc_max_retries
150176 for i in range (vector_client_max_retries ):
177+ vector_db_container : Optional [CustomMilvusContainer ] = None
151178 try :
152179 vector_db_container = CustomMilvusContainer (
153180 image = image ,
154181 service_container_port = service_container_port ,
155182 healthcheck_container_port = healthcheck_container_port )
156- vector_db_container = vector_db_container .with_volume_mapping (
183+ mapped_container = vector_db_container .with_volume_mapping (
157184 cfg , "/milvus/configs/user.yaml" )
158- vector_db_container .start ()
159- host = vector_db_container .get_container_host_ip ()
160- port = vector_db_container .get_exposed_port (service_container_port )
161- info = VectorDBContainerInfo (vector_db_container , host , port )
185+ assert mapped_container is not None
186+ running_container : CustomMilvusContainer = mapped_container
187+ vector_db_container = running_container
188+ running_container .start ()
189+ host = running_container .get_container_host_ip ()
190+ port = running_container .get_exposed_port (service_container_port )
191+ info = VectorDBContainerInfo (running_container , host , port )
192+ MilvusTestHelpers ._wait_for_milvus_grpc (info .uri )
162193 _LOGGER .info (
163194 "milvus db container started successfully on %s." , info .uri )
195+ break
164196 except Exception as e :
165- stdout_logs , stderr_logs = vector_db_container .get_logs ()
166- stdout_logs = stdout_logs .decode ("utf-8" )
167- stderr_logs = stderr_logs .decode ("utf-8" )
197+ stdout_logs = stderr_logs = ""
198+ if vector_db_container is not None :
199+ raw_out , raw_err = vector_db_container .get_logs ()
200+ stdout_logs = raw_out .decode ("utf-8" )
201+ stderr_logs = raw_err .decode ("utf-8" )
168202 _LOGGER .warning (
169203 "Retry %d/%d: Failed to start Milvus DB container. Reason: %s. "
170204 "STDOUT logs:\n %s\n STDERR logs:\n %s" ,
0 commit comments