Пытаюсь работать с Java JDO, но как я понимаю проблема в самом datastore. Из-за кучи ограничений на структуру базы и использования транзакций, возникает необходимость создавать транзакции хотя бы для некоторых объектов, структуру которых можно сделать намеренно простой.
Задача вообще то немного другая:
Упрощенный пример:
Есть 2 типа объектов — User {id,name} и Item {id,name,user_owner:nullable}, связь между ними Один-ко-Многим, при этом могут существовать экземпляры объекта Item, никому не принадлежащие. Экземпляры Item могут перемещаться между разными User
Т.е. в данном примере, в терминах GAE datastore, корневой объект может становиться наследуемым и обратно. Штатные 'отношения' не позволяют (точнее мне не удалось) перемещать экземпляры Item между разными User (даже если вызывать pm.makePersistent после каждого изменения...) и поэтому приходится реализовывать отношения через идентификаторы, а их получение при создании, через сиквенсы (хорошо хоть они поддерживаются, хотя собственный счетчик завести не проблема… почти), так как по другому нет никакой возможности узнать, какой идентификатор система выдала новому объекту, пока он не будет сохранен или pm.close().
Все было бы хорошо, реализация отношений через свои ключи не накладывает никаких ограничений на их тип, но появляется проблема с транзакциями — в GAE datastore транзакции действуют исключительно в пределах одной группы объектов (а группа — это связанные штатными отношениями 1-М или 1-1, на самом деле там появляются еще ограничения).
Как понимаете, практически невозможно создать и поддерживать более-менее сложную базу без транзакций, тем более, если сама платформа, практически на любой чих, может прервать выполнение запроса в любом месте… если откат изменений еще можно произвести вручную (хотя это еще та задачка), то как организовать блокировку на доступ без транзакций..?
Так как транзакции в GAE это фактически блокировка на уровне экземпляров объектов, хотелось бы иметь возможность блокировать доступ к указанным объектам, причем по списку
Например в указанном примере:
Можно для 'ничейных' Item создать фиктивный экземпляр объекта User
Соответственно блокировку проводить только на доступ к объектам User
Естественно может потребоваться в пределах одной транзакции блокировать доступ сразу к нескольким экземплярам User.
Например при перемещении Item Между разными User можно сначала блокировать доступ к этим User а потом провести перемещение, соответственно присвоение 'свободных' Item или 'освобождение' занятых, получается точно такая же задача.
Как можно вообще такое реализовать, может будут еще идеи? Неужели никто с этой типичной задачей на GAE не сталкивался или все надеются 'на авось', или GAE как то недокументированно защищает приложения от параллельного доступа к данным?
p.s. лучшее что приходит в голову, организовать собственные семафоры на основе memcache (MemcacheService.Put с использованием стратегии ADD_ONLY_IF_NOT_PRESENT ) но это так же ничего не гарантирует, хотя на много порядков уменьшает вероятность сбоя (вероятность того что значение из кэша будет удалено быстрее, чем закончится 'транзакция' исчезающе мало, хотя есть шанс что при переносе между физическими инстансами приложение не будет видеть созданные ранее значения)