Таблица хранения Azure [Python] - Пакет не дает сбоя
В настоящее время я занимаюсь разработкой приложения Python (2.7), которое использует службу хранилища таблиц Azure через пакет Azure Python. Насколько я читал из REST API Azure, пакетные операции создают атомарные транзакции. Таким образом, если одна из операций завершается неудачей, весь пакет завершается неудачно, и никакие операции не выполняются.
Проблема, с которой я столкнулся, заключается в следующем: метод, указанный ниже, получает через параметр "rows" список диктов. У некоторых есть набор ETag (предоставленный из предыдущего запроса).
Если ETag установлен,попытайтесь выполнить операцию слияния. В противном случае, попробуйте операцию вставки. Поскольку существует несколько процессов, которые могут изменять одну и ту же сущность, необходимо решить проблему параллелизма с помощью параметра if_match функции merge_entity. Если операции слияния / вставки являются отдельными операциями (не включенными в пакет), система работает должным образом, вызывая исключение, если ETag не совпадают. К сожалению, этого не происходит, если они заключены в вызовы "begin_batch" / "commit_batch". Объекты объединяются (ошибочно), даже если ETag НЕ совпадают.
Я предоставил ниже и код и используемый тестовый пример. Также провел несколько ручных тестов несколько раз с тем же выводом.
Я не уверен, как подойти к этой проблеме. Я делаю что-то не так или это проблема с пакетом Python?
Используемый код следующий:
def persist_entities(self, rows):
success = True
self._service.begin_batch() #If commented, works as expected (fails)
for row in rows:
print row
etag = row.pop("ETag")
if not etag:
self._service.insert_entity(self._name,
entity=row)
else:
print "Merging " + etag
self._service.merge_entity(self._name,
row["PartitionKey"],
row["RowKey"],
row, if_match=etag)
try: #Also tried with the try at the begining of the code
self._service.commit_batch() #If commented, works as expected (fails)
except WindowsAzureError:
print "Failed to merge"
self._service.cancel_batch()
success = False
return success
Используемый тестовый пример:
def test_fail_update(self):
service = self._conn.get_service()
partition, new_rows = self._generate_data() #Partition key and list of dicts
success = self._wrapper.persist_entities(new_rows) #Inserts fresh new entity
ok_(success) #Insert succeeds
rows = self._wrapper.get_entities_by_row(partition) #Retreives inserted data for ETag
eq_(len(rows), 1)
for index in rows:
row = rows[index]
data = new_rows[0]
data["Count"] = 155 #Same data, different value
data["ETag"] = "random_etag" #Change ETag to a random string
val = self._wrapper.persist_entities([data]) #Try to merge
ok_(not val) #val = True for merge success, False for merge fail.
#It's always True when operations in batch. False if operations out of batch
rows1 = self._wrapper.get_entities_by_row(partition)
eq_(len(rows1), 1)
eq_(rows1[index].Count, 123)
break
def _generate_data(self):
date = datetime.now().isoformat()
partition = "{0}_{1}_{2}".format("1",
Stats.RESOLUTION_DAY, date)
data = {
"PartitionKey": partition,
"RowKey": "viewitem",
"Count": 123,
"ETag": None
}
return partition, [data]
2 ответа
Это ошибка в SDK (v0.8 и ранее). Я создал проблему и проверил исправление. Это будет частью следующего релиза. Вы можете установить pip из git repo, чтобы проверить исправление. https://github.com/Azure/azure-sdk-for-python/issues/149
В хранилище таблиц Azure есть новая библиотека python в предварительной версии, которая доступна для установки через pip. Для установки используйте следующую команду pip
pip install azure-data-tables
Есть некоторые различия в том, как вы выполняете пакетную обработку и как она работает в новейшей библиотеке.
- Пакетная операция может быть зафиксирована только для объектов, содержащих один и тот же ключ раздела.
- Пакетная операция не может содержать несколько операций с одним и тем же ключом строки.
- Пакеты будут зафиксированы только в том случае, если весь пакет будет успешным, если
send_batch
выдает ошибку, обновлений делать не будет.
При этом операции создания и обновления работают так же, как и создание и обновление без пакетной обработки. Например:
from azure.data.tables import TableClient, UpdateMode
table_client = TableClient.from_connection_string(conn_str, table_name="myTable")
batch = table_client.create_batch()
batch.create_entity(entity1)
batch.update_entity(entity2, etag=etag, match_condition=UpdateMode.MERGE)
batch.delete_entity(entity['PartitionKey'], entity['RowKey'])
try:
table_client.send_batch(batch)
except BatchErrorException as e:
print("There was an error with the batch")
print(e)
Дополнительные образцы с новой библиотекой можно найти на странице образцов в репозитории.
(К вашему сведению, я сотрудник Microsoft в команде Azure SDK для Python)