11import uuid
2+ import time
23from eventsourcingdb .client import Client
34from eventsourcingdb .container import Container
45from .testing_database import TestingDatabase
6+ import os
57
68class Database :
79 __create_key = object ()
@@ -19,34 +21,75 @@ def __init__(
1921 self .with_invalid_url : TestingDatabase = with_invalid_url
2022
2123 @classmethod
22- async def create (cls ) -> 'Database' :
24+ async def create (cls , max_retries = 3 , retry_delay = 2.0 ) -> 'Database' :
25+ """Create a new Database instance with retry mechanism for container startup"""
2326 api_token = str (uuid .uuid4 ())
2427
25- # Erstellen und Starten des Containers mit der zentralen Container-Klasse
28+ dockerfile_path = os .path .join (os .path .dirname (__file__ ), 'docker/eventsourcingdb/Dockerfile' )
29+ with open (dockerfile_path , 'r' ) as dockerfile :
30+ content = dockerfile .read ().strip ()
31+ image_tag = content .split (':' )[- 1 ]
32+
2633 container = Container (
27- api_token = api_token
34+ image_name = "thenativeweb/eventsourcingdb" ,
35+ image_tag = image_tag ,
36+ api_token = api_token ,
37+ internal_port = 3000
2838 )
29- container .start ()
3039
31- # Client mit Autorisierung erstellen
32- with_authorization_client = container .get_client ()
33- await with_authorization_client .initialize ()
34- with_authorization = TestingDatabase (
35- with_authorization_client ,
36- container # Container an TestingDatabase übergeben für cleanup
37- )
40+ # Try with retries
41+ for attempt in range (max_retries ):
42+ try :
43+ # Start the container with timeout handling
44+ container .start ()
45+
46+ # Create client with authorization
47+ with_authorization_client = container .get_client ()
48+ await with_authorization_client .initialize ()
49+ with_authorization = TestingDatabase (
50+ with_authorization_client ,
51+ container # Pass container to TestingDatabase for cleanup
52+ )
3853
39- # Client mit ungültiger URL erstellen - api_token statt auth_token verwenden
40- with_invalid_url_client = Client (
41- base_url = 'http://localhost.invalid' ,
42- api_token = api_token
43- )
44- await with_invalid_url_client .initialize ()
45- with_invalid_url = TestingDatabase (
46- with_invalid_url_client
47- )
54+ # Create client with invalid URL but valid token
55+ with_invalid_url_client = Client (
56+ base_url = 'http://localhost.invalid' ,
57+ api_token = api_token
58+ )
59+ await with_invalid_url_client .initialize ()
60+ with_invalid_url = TestingDatabase (
61+ with_invalid_url_client
62+ )
4863
49- return cls (Database .__create_key , with_authorization , with_invalid_url )
64+ return cls (Database .__create_key , with_authorization , with_invalid_url )
65+
66+ except Exception as e :
67+ # On the last attempt, raise the error
68+ if attempt == max_retries - 1 :
69+ # Cleanup the container if it was created
70+ try :
71+ container .stop ()
72+ except :
73+ pass
74+ raise RuntimeError (f"Failed to initialize database container after { max_retries } attempts: { e } " )
75+
76+ # Otherwise wait and retry
77+ print (f"Container startup attempt { attempt + 1 } failed: { e } . Retrying in { retry_delay } seconds..." )
78+ time .sleep (retry_delay )
79+
80+ # Try to clean up the failed container before retrying
81+ try :
82+ container .stop ()
83+ except :
84+ pass
85+
86+ # Create a new container for the next attempt
87+ container = Container (
88+ image_name = "thenativeweb/eventsourcingdb" ,
89+ image_tag = "latest" ,
90+ api_token = api_token ,
91+ internal_port = 3000
92+ )
5093
5194 async def stop (self ):
5295 await self .with_authorization .stop ()
0 commit comments