altcodepro-polydb-python 2.2.2__py3-none-any.whl → 2.2.4__py3-none-any.whl

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 (38) hide show
  1. altcodepro_polydb_python-2.2.4.dist-info/METADATA +489 -0
  2. altcodepro_polydb_python-2.2.4.dist-info/RECORD +57 -0
  3. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/WHEEL +1 -1
  4. polydb/__init__.py +2 -2
  5. polydb/adapters/AzureBlobStorageAdapter.py +146 -41
  6. polydb/adapters/AzureFileStorageAdapter.py +148 -43
  7. polydb/adapters/AzureQueueAdapter.py +96 -34
  8. polydb/adapters/AzureTableStorageAdapter.py +462 -119
  9. polydb/adapters/BlockchainBlobAdapter.py +111 -0
  10. polydb/adapters/BlockchainKVAdapter.py +152 -0
  11. polydb/adapters/BlockchainQueueAdapter.py +116 -0
  12. polydb/adapters/DynamoDBAdapter.py +463 -176
  13. polydb/adapters/FirestoreAdapter.py +320 -148
  14. polydb/adapters/GCPPubSubAdapter.py +217 -0
  15. polydb/adapters/GCPStorageAdapter.py +184 -39
  16. polydb/adapters/MongoDBAdapter.py +159 -39
  17. polydb/adapters/PostgreSQLAdapter.py +285 -83
  18. polydb/adapters/S3Adapter.py +172 -35
  19. polydb/adapters/S3CompatibleAdapter.py +62 -8
  20. polydb/adapters/SQSAdapter.py +121 -44
  21. polydb/adapters/VercelBlobAdapter.py +196 -0
  22. polydb/adapters/VercelKVAdapter.py +275 -283
  23. polydb/adapters/VercelQueueAdapter.py +61 -0
  24. polydb/audit/AuditStorage.py +1 -1
  25. polydb/base/NoSQLKVAdapter.py +113 -101
  26. polydb/base/ObjectStorageAdapter.py +42 -6
  27. polydb/base/QueueAdapter.py +2 -2
  28. polydb/base/SharedFilesAdapter.py +2 -2
  29. polydb/cloudDatabaseFactory.py +200 -0
  30. polydb/databaseFactory.py +434 -101
  31. polydb/models.py +63 -1
  32. polydb/query.py +111 -42
  33. altcodepro_polydb_python-2.2.2.dist-info/METADATA +0 -379
  34. altcodepro_polydb_python-2.2.2.dist-info/RECORD +0 -52
  35. polydb/adapters/PubSubAdapter.py +0 -85
  36. polydb/factory.py +0 -107
  37. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/licenses/LICENSE +0 -0
  38. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/top_level.txt +0 -0
@@ -1,77 +1,182 @@
1
1
  # src/polydb/adapters/AzureBlobStorageAdapter.py
2
2
 
3
- from polydb.base.ObjectStorageAdapter import ObjectStorageAdapter
4
- from polydb.errors import ConnectionError, StorageError
5
- from polydb.retry import retry
6
3
  import os
7
4
  import threading
8
- from typing import List
5
+ from typing import Any, Dict, List, Optional
6
+ import mimetypes
7
+ from azure.storage.blob import BlobServiceClient, ContainerClient, ContentSettings
8
+ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError
9
+
10
+ from ..base.ObjectStorageAdapter import ObjectStorageAdapter
11
+ from ..errors import ConnectionError, StorageError
12
+ from ..retry import retry
13
+
9
14
 
10
15
  class AzureBlobStorageAdapter(ObjectStorageAdapter):
11
- """Azure Blob Storage with client reuse"""
16
+ """
17
+ Production-grade Azure Blob Storage adapter.
18
+
19
+ Features
20
+ - Thread-safe client initialization
21
+ - Container auto-creation
22
+ - Retry support
23
+ - Structured logging
24
+ - Connection reuse
25
+ """
12
26
 
13
- def __init__(self):
27
+ def __init__(self, connection_string: str = "", container_name: str = ""):
14
28
  super().__init__()
15
- self.connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING") or ""
16
- self.container_name = os.getenv("AZURE_CONTAINER_NAME", "default") or ""
17
- self._client = None
29
+
30
+ self.connection_string = connection_string or os.getenv("AZURE_STORAGE_CONNECTION_STRING")
31
+ self.container_name = container_name or os.getenv("AZURE_CONTAINER_NAME", "polydb")
32
+
33
+ if not self.connection_string:
34
+ raise ConnectionError("AZURE_STORAGE_CONNECTION_STRING is not configured")
35
+
36
+ self._client: Optional[BlobServiceClient] = None
37
+ self._container: Optional[ContainerClient] = None
18
38
  self._lock = threading.Lock()
39
+
19
40
  self._initialize_client()
20
41
 
21
- def _initialize_client(self):
22
- """Initialize Azure Blob Storage client once"""
42
+ def _initialize_client(self) -> None:
43
+ """Initialize Azure Blob client and container"""
23
44
  try:
24
- from azure.storage.blob import BlobServiceClient
25
-
26
45
  with self._lock:
27
- if not self._client:
28
- self._client = BlobServiceClient.from_connection_string(self.connection_string)
29
- self.logger.info("Initialized Azure Blob Storage client")
46
+ if self._client is not None:
47
+ return
48
+ if not self.connection_string:
49
+ raise ConnectionError("AZURE_STORAGE_CONNECTION_STRING is not configured")
50
+ self._client = BlobServiceClient.from_connection_string(self.connection_string)
51
+
52
+ self._container = self._client.get_container_client(self.container_name)
53
+
54
+ try:
55
+ self._container.create_container()
56
+ self.logger.info(f"Created container: {self.container_name}")
57
+ except ResourceExistsError:
58
+ pass
59
+
60
+ self.logger.info(
61
+ f"Azure Blob Storage initialized (container={self.container_name})"
62
+ )
63
+
30
64
  except Exception as e:
31
- raise ConnectionError(f"Failed to initialize Azure Blob Storage: {str(e)}")
65
+ raise ConnectionError(f"Failed to initialize Azure Blob Storage: {e}")
66
+
67
+ def _require_container(self) -> ContainerClient:
68
+ """Ensure container exists"""
69
+ if self._container is None:
70
+ raise ConnectionError("Azure Blob Storage client is not initialized")
71
+ return self._container
32
72
 
33
73
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
34
- def _put_raw(self, key: str, data: bytes) -> str:
35
- """Store blob"""
74
+ def _put_raw(
75
+ self,
76
+ key: str,
77
+ data: bytes,
78
+ fileName: str = "",
79
+ media_type: Optional[str] = None,
80
+ metadata: Dict[str, Any] | None = None,
81
+ ) -> str:
82
+ """Upload blob with filename, media type, and metadata"""
36
83
  try:
37
- if self._client:
38
- blob_client = self._client.get_blob_client(self.container_name, key)
39
- blob_client.upload_blob(data, overwrite=True)
40
- self.logger.debug(f"Uploaded blob: {key}")
41
- return key
84
+ container = self._require_container()
85
+
86
+ # --------------------------------------------------
87
+ # Resolve filename
88
+ # --------------------------------------------------
89
+ filename = fileName or os.path.basename(key)
90
+
91
+ # --------------------------------------------------
92
+ # Ensure extension from media_type if missing
93
+ # --------------------------------------------------
94
+ if media_type:
95
+ ext = mimetypes.guess_extension(media_type) or ""
96
+ if ext and not filename.lower().endswith(ext):
97
+ filename += ext
98
+
99
+ # --------------------------------------------------
100
+ # Final blob key (include filename if needed)
101
+ # --------------------------------------------------
102
+ blob_key = key
103
+ if fileName:
104
+ blob_key = f"{key.rstrip('/')}/{filename}"
105
+
106
+ blob_client = container.get_blob_client(blob_key)
107
+
108
+ # --------------------------------------------------
109
+ # Upload with content type + metadata
110
+ # --------------------------------------------------
111
+ blob_client.upload_blob(
112
+ data,
113
+ overwrite=True,
114
+ content_settings=ContentSettings(
115
+ content_type=media_type or "application/octet-stream"
116
+ ),
117
+ metadata={
118
+ **(metadata or {}),
119
+ "filename": filename,
120
+ },
121
+ )
122
+
123
+ self.logger.debug(f"Uploaded blob key={blob_key}, type={media_type}")
124
+
125
+ return blob_client.url
126
+
42
127
  except Exception as e:
43
- raise StorageError(f"Azure Blob put failed: {str(e)}")
128
+ raise StorageError(f"Azure Blob put failed: {e}")
44
129
 
45
130
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
46
131
  def get(self, key: str) -> bytes | None:
47
- """Get blob"""
132
+ """Download blob"""
48
133
  try:
49
- if self._client:
50
- blob_client = self._client.get_blob_client(self.container_name, key)
51
- return blob_client.download_blob().readall()
134
+ container = self._require_container()
135
+
136
+ blob_client = container.get_blob_client(key)
137
+
138
+ downloader = blob_client.download_blob()
139
+ data = downloader.readall()
140
+
141
+ self.logger.debug(f"Downloaded blob key={key}")
142
+
143
+ return data
144
+
145
+ except ResourceNotFoundError:
52
146
  return None
53
147
  except Exception as e:
54
- raise StorageError(f"Azure Blob get failed: {str(e)}")
148
+ raise StorageError(f"Azure Blob get failed: {e}")
55
149
 
56
150
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
57
151
  def delete(self, key: str) -> bool:
58
152
  """Delete blob"""
59
153
  try:
60
- if self._client:
61
- blob_client = self._client.get_blob_client(self.container_name, key)
62
- blob_client.delete_blob()
63
- return True
154
+ container = self._require_container()
155
+
156
+ blob_client = container.get_blob_client(key)
157
+ blob_client.delete_blob(delete_snapshots="include")
158
+
159
+ self.logger.debug(f"Deleted blob key={key}")
160
+
161
+ return True
162
+
163
+ except ResourceNotFoundError:
64
164
  return False
65
165
  except Exception as e:
66
- raise StorageError(f"Azure Blob delete failed: {str(e)}")
166
+ raise StorageError(f"Azure Blob delete failed: {e}")
67
167
 
68
168
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
69
169
  def list(self, prefix: str = "") -> List[str]:
70
- """List blobs with prefix"""
170
+ """List blobs"""
71
171
  try:
72
- if self._client:
73
- container_client = self._client.get_container_client(self.container_name)
74
- return [blob.name for blob in container_client.list_blobs(name_starts_with=prefix)]
75
- return []
172
+ container = self._require_container()
173
+
174
+ blobs = container.list_blobs(name_starts_with=prefix)
175
+ results = [blob.name for blob in blobs]
176
+
177
+ self.logger.debug(f"Listed {len(results)} blobs prefix={prefix}")
178
+
179
+ return results
180
+
76
181
  except Exception as e:
77
- raise StorageError(f"Azure Blob list failed: {str(e)}")
182
+ raise StorageError(f"Azure Blob list failed: {e}")
@@ -1,79 +1,184 @@
1
1
  # src/polydb/adapters/AzureFileStorageAdapter.py
2
2
 
3
- from polydb.base.SharedFilesAdapter import SharedFilesAdapter
4
- from polydb.errors import ConnectionError, StorageError
5
- from polydb.retry import retry
3
+ from __future__ import annotations
4
+
6
5
  import os
7
6
  import threading
8
- from typing import List
7
+ from typing import List, Optional
8
+
9
+ from azure.storage.fileshare import ShareServiceClient
10
+ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError
11
+
12
+ from ..base.SharedFilesAdapter import SharedFilesAdapter
13
+ from ..errors import ConnectionError, StorageError
14
+ from ..retry import retry
15
+
9
16
 
10
17
  class AzureFileStorageAdapter(SharedFilesAdapter):
11
- """Azure File Storage with client reuse"""
18
+ """
19
+ Production-grade Azure File Storage adapter.
20
+
21
+ Fixes:
22
+ - Adds upload/download methods expected by tests
23
+ - Ensures share exists
24
+ - Ensures directory structure exists
25
+ - Correct Azure file creation before upload
26
+ - Keeps write/read compatibility
27
+ """
12
28
 
13
- def __init__(self):
29
+ def __init__(self, connection_string: str = "", share_name: str = ""):
14
30
  super().__init__()
15
- self.connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING") or ""
16
- self.share_name = os.getenv("AZURE_SHARE_NAME", "default") or ""
17
- self._client = None
31
+
32
+ self.connection_string = (
33
+ connection_string or os.getenv("AZURE_STORAGE_CONNECTION_STRING") or ""
34
+ )
35
+
36
+ self.share_name = share_name or os.getenv("AZURE_SHARE_NAME", "polydb")
37
+
38
+ if not self.connection_string:
39
+ raise ConnectionError("AZURE_STORAGE_CONNECTION_STRING not configured")
40
+
41
+ self._client: Optional[ShareServiceClient] = None
42
+ self._share = None
18
43
  self._lock = threading.Lock()
44
+
19
45
  self._initialize_client()
20
46
 
47
+ # --------------------------------------------------
48
+ # Client initialization
49
+ # --------------------------------------------------
50
+
21
51
  def _initialize_client(self):
22
- """Initialize Azure File Storage client once"""
23
52
  try:
24
- from azure.storage.fileshare import ShareServiceClient
25
-
26
53
  with self._lock:
27
- if not self._client:
28
- self._client = ShareServiceClient.from_connection_string(self.connection_string)
29
- self.logger.info("Initialized Azure File Storage client")
54
+ if self._client:
55
+ return
56
+
57
+ self._client = ShareServiceClient.from_connection_string(self.connection_string)
58
+
59
+ self._share = self._client.get_share_client(self.share_name)
60
+
61
+ try:
62
+ self._share.create_share()
63
+ except ResourceExistsError:
64
+ pass
65
+
66
+ self.logger.info("Initialized Azure File Storage client")
67
+
30
68
  except Exception as e:
31
69
  raise ConnectionError(f"Failed to initialize Azure File Storage: {str(e)}")
32
70
 
71
+ # --------------------------------------------------
72
+ # Helpers
73
+ # --------------------------------------------------
74
+
75
+ def _split_path(self, path: str):
76
+ if "/" not in path:
77
+ return "", path
78
+
79
+ directory, filename = path.rsplit("/", 1)
80
+ return directory, filename
81
+
82
+ def _ensure_directory(self, directory: str):
83
+ if not directory and self._share:
84
+ return self._share.get_directory_client("")
85
+ if not self._share:
86
+ raise ConnectionError("Azure File Storage share not initialized")
87
+ dir_client = self._share.get_directory_client(directory)
88
+
89
+ try:
90
+ dir_client.create_directory()
91
+ except ResourceExistsError:
92
+ pass
93
+
94
+ return dir_client
95
+
96
+ # --------------------------------------------------
97
+ # Core operations
98
+ # --------------------------------------------------
99
+
33
100
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
34
- def write(self, path: str, data: bytes) -> bool:
35
- """Write file"""
101
+ def upload(self, path: str, data: bytes) -> str:
102
+ """Upload file"""
36
103
  try:
37
- if self._client:
38
- file_client = self._client.get_share_client(self.share_name).get_file_client(path)
39
- file_client.upload_file(data)
40
- return True
41
- return False
104
+ directory, filename = self._split_path(path)
105
+
106
+ dir_client = self._ensure_directory(directory)
107
+ file_client = dir_client.get_file_client(filename)
108
+
109
+ file_client.create_file(len(data))
110
+ file_client.upload_file(data)
111
+
112
+ return path
113
+
42
114
  except Exception as e:
43
- raise StorageError(f"Azure File write failed: {str(e)}")
115
+ raise StorageError(f"Azure File upload failed: {str(e)}")
44
116
 
45
117
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
46
- def read(self, path: str) -> bytes | None:
47
- """Read file"""
118
+ def download(self, path: str) -> bytes:
119
+ """Download file"""
48
120
  try:
49
- if self._client:
50
- file_client = self._client.get_share_client(self.share_name).get_file_client(path)
51
- return file_client.download_file().readall()
52
- return None
121
+ directory, filename = self._split_path(path)
122
+ if not self._share:
123
+ raise ConnectionError("Azure File Storage share not initialized")
124
+ dir_client = self._share.get_directory_client(directory or "")
125
+ file_client = dir_client.get_file_client(filename)
126
+
127
+ return file_client.download_file().readall()
128
+
129
+ except ResourceNotFoundError:
130
+ raise StorageError(f"File not found: {path}")
53
131
  except Exception as e:
54
- raise StorageError(f"Azure File read failed: {str(e)}")
132
+ raise StorageError(f"Azure File download failed: {str(e)}")
55
133
 
56
134
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
57
135
  def delete(self, path: str) -> bool:
58
136
  """Delete file"""
59
137
  try:
60
- if self._client:
61
- file_client = self._client.get_share_client(self.share_name).get_file_client(path)
62
- file_client.delete_file()
63
- return True
138
+ directory, filename = self._split_path(path)
139
+ if not self._share:
140
+ raise ConnectionError("Azure File Storage share not initialized")
141
+ dir_client = self._share.get_directory_client(directory or "")
142
+ file_client = dir_client.get_file_client(filename)
143
+
144
+ file_client.delete_file()
145
+ return True
146
+
147
+ except ResourceNotFoundError:
64
148
  return False
65
149
  except Exception as e:
66
150
  raise StorageError(f"Azure File delete failed: {str(e)}")
67
151
 
68
152
  @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
69
- def list(self, directory: str = "/") -> List[str]:
70
- """List files in directory"""
153
+ def list(self, directory: str = "") -> List[str]:
154
+ """List files"""
71
155
  try:
72
- if self._client:
73
- dir_client = self._client.get_share_client(self.share_name).get_directory_client(
74
- directory
75
- )
76
- return [item.name for item in dir_client.list_directories_and_files()]
77
- return []
156
+ if not self._share:
157
+ raise ConnectionError("Azure File Storage share not initialized")
158
+ dir_client = self._share.get_directory_client(directory or "")
159
+
160
+ results: List[str] = []
161
+
162
+ for item in dir_client.list_directories_and_files():
163
+ results.append(item.name)
164
+
165
+ return results
166
+
78
167
  except Exception as e:
79
- raise StorageError(f"Azure File list failed: {str(e)}")
168
+ raise StorageError(f"Azure File list failed: {str(e)}")
169
+
170
+ # --------------------------------------------------
171
+ # Backward compatibility
172
+ # --------------------------------------------------
173
+
174
+ def write(self, path: str, data: bytes) -> bool:
175
+ """Alias for upload"""
176
+ self.upload(path, data)
177
+ return True
178
+
179
+ def read(self, path: str) -> bytes | None:
180
+ """Alias for download"""
181
+ try:
182
+ return self.download(path)
183
+ except StorageError:
184
+ return None
@@ -1,63 +1,125 @@
1
1
  # src/polydb/adapters/AzureQueueAdapter.py
2
- from polydb.base.QueueAdapter import QueueAdapter
3
- from polydb.errors import ConnectionError, QueueError
4
- from polydb.retry import retry
2
+
5
3
  import os
6
4
  import threading
7
- from typing import Any, Dict, List
5
+ import json
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ from azure.storage.queue import QueueServiceClient, QueueClient
9
+ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError
8
10
 
11
+ from ..base.QueueAdapter import QueueAdapter
12
+ from ..errors import ConnectionError, QueueError
13
+ from ..retry import retry
9
14
  from ..json_safe import json_safe
10
15
 
16
+
11
17
  class AzureQueueAdapter(QueueAdapter):
12
- """Azure Queue Storage with client reuse"""
18
+ """
19
+ Azure Queue Storage adapter.
20
+
21
+ Features
22
+ - Thread-safe initialization
23
+ - Automatic queue creation
24
+ - Client reuse
25
+ - Retry support
26
+ """
13
27
 
14
- def __init__(self):
28
+ def __init__(self, connection_string: str = ""):
15
29
  super().__init__()
16
- self.connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING") or ""
17
- self._client = None
30
+
31
+ self.connection_string = connection_string or os.getenv("AZURE_STORAGE_CONNECTION_STRING")
32
+
33
+ if not self.connection_string:
34
+ raise ConnectionError("AZURE_STORAGE_CONNECTION_STRING is not configured")
35
+
36
+ self._client: Optional[QueueServiceClient] = None
37
+ self._queues: Dict[str, QueueClient] = {}
38
+
18
39
  self._lock = threading.Lock()
40
+
19
41
  self._initialize_client()
20
42
 
21
- def _initialize_client(self):
22
- """Initialize Azure Queue Storage client once"""
43
+ def _initialize_client(self) -> None:
44
+ """Initialize Azure Queue client"""
23
45
  try:
24
- from azure.storage.queue import QueueServiceClient
25
-
26
46
  with self._lock:
27
- if not self._client:
28
- self._client = QueueServiceClient.from_connection_string(self.connection_string)
29
- self.logger.info("Initialized Azure Queue Storage client")
47
+ if self._client is not None:
48
+ return
49
+ if not self.connection_string:
50
+ raise ConnectionError("AZURE_STORAGE_CONNECTION_STRING is not configured")
51
+ self._client = QueueServiceClient.from_connection_string(self.connection_string)
52
+
53
+ self.logger.info("Initialized Azure Queue Storage client")
54
+
30
55
  except Exception as e:
31
- raise ConnectionError(f"Failed to initialize Azure Queue Storage: {str(e)}")
56
+ raise ConnectionError(f"Failed to initialize Azure Queue Storage: {e}")
57
+
58
+ def _get_queue(self, queue_name: str) -> QueueClient:
59
+ """Get or create queue client"""
60
+ if self._client is None:
61
+ raise ConnectionError("Azure Queue client not initialized")
62
+
63
+ if queue_name not in self._queues:
64
+ queue_client = self._client.get_queue_client(queue_name)
65
+
66
+ try:
67
+ queue_client.create_queue()
68
+ except ResourceExistsError:
69
+ pass
70
+
71
+ self._queues[queue_name] = queue_client
72
+
73
+ return self._queues[queue_name]
32
74
 
33
75
  @retry(max_attempts=3, delay=1.0, exceptions=(QueueError,))
34
76
  def send(self, message: Dict[str, Any], queue_name: str = "default") -> str:
35
77
  """Send message to queue"""
36
78
  try:
37
- import json
79
+ queue_client = self._get_queue(queue_name)
80
+
81
+ response = queue_client.send_message(json.dumps(message, default=json_safe))
82
+
83
+ return response.id
38
84
 
39
- if self._client:
40
- queue_client = self._client.get_queue_client(queue_name)
41
- response = queue_client.send_message(json.dumps(message,default=json_safe))
42
- return response.id
43
- return ""
44
85
  except Exception as e:
45
- raise QueueError(f"Azure Queue send failed: {str(e)}")
86
+ raise QueueError(f"Azure Queue send failed: {e}")
46
87
 
47
88
  @retry(max_attempts=3, delay=1.0, exceptions=(QueueError,))
48
89
  def receive(self, queue_name: str = "default", max_messages: int = 1) -> List[Dict[str, Any]]:
49
- """Receive messages from queue"""
90
+ """Receive messages"""
50
91
  try:
51
- import json
92
+ queue_client = self._get_queue(queue_name)
93
+
94
+ messages = queue_client.receive_messages(max_messages=max_messages)
95
+
96
+ results = []
97
+
98
+ for msg in messages:
99
+ payload = json.loads(msg.content)
100
+ results.append(
101
+ {
102
+ "id": msg.id,
103
+ "pop_receipt": msg.pop_receipt,
104
+ "body": payload,
105
+ }
106
+ )
107
+
108
+ return results
52
109
 
53
- if self._client:
54
- queue_client = self._client.get_queue_client(queue_name)
55
- messages = queue_client.receive_messages(max_messages=max_messages)
56
- return [json.loads(msg.content) for msg in messages]
57
- return []
58
110
  except Exception as e:
59
- raise QueueError(f"Azure Queue receive failed: {str(e)}")
111
+ raise QueueError(f"Azure Queue receive failed: {e}")
112
+
113
+ def delete(self, message_id: str, queue_name: str = "default", pop_receipt: str = "") -> bool:
114
+ """Delete message from queue"""
115
+ try:
116
+ queue_client = self._get_queue(queue_name)
60
117
 
61
- def delete(self, message_id: str, queue_name: str = "default") -> bool:
62
- """Delete message from queue (requires receipt handle)"""
63
- return True
118
+ queue_client.delete_message(message_id, pop_receipt)
119
+
120
+ return True
121
+
122
+ except ResourceNotFoundError:
123
+ return False
124
+ except Exception as e:
125
+ raise QueueError(f"Azure Queue delete failed: {e}")