nucliadb 2.46.1.post382__py3-none-any.whl → 6.2.1.post2777__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 (431) hide show
  1. migrations/0002_rollover_shards.py +1 -2
  2. migrations/0003_allfields_key.py +2 -37
  3. migrations/0004_rollover_shards.py +1 -2
  4. migrations/0005_rollover_shards.py +1 -2
  5. migrations/0006_rollover_shards.py +2 -4
  6. migrations/0008_cleanup_leftover_rollover_metadata.py +1 -2
  7. migrations/0009_upgrade_relations_and_texts_to_v2.py +5 -4
  8. migrations/0010_fix_corrupt_indexes.py +11 -12
  9. migrations/0011_materialize_labelset_ids.py +2 -18
  10. migrations/0012_rollover_shards.py +6 -12
  11. migrations/0013_rollover_shards.py +2 -4
  12. migrations/0014_rollover_shards.py +5 -7
  13. migrations/0015_targeted_rollover.py +6 -12
  14. migrations/0016_upgrade_to_paragraphs_v2.py +27 -32
  15. migrations/0017_multiple_writable_shards.py +3 -6
  16. migrations/0018_purge_orphan_kbslugs.py +59 -0
  17. migrations/0019_upgrade_to_paragraphs_v3.py +66 -0
  18. migrations/0020_drain_nodes_from_cluster.py +83 -0
  19. nucliadb/standalone/tests/unit/test_run.py → migrations/0021_overwrite_vectorsets_key.py +17 -18
  20. nucliadb/tests/unit/test_openapi.py → migrations/0022_fix_paragraph_deletion_bug.py +16 -11
  21. migrations/0023_backfill_pg_catalog.py +80 -0
  22. migrations/0025_assign_models_to_kbs_v2.py +113 -0
  23. migrations/0026_fix_high_cardinality_content_types.py +61 -0
  24. migrations/0027_rollover_texts3.py +73 -0
  25. nucliadb/ingest/fields/date.py → migrations/pg/0001_bootstrap.py +10 -12
  26. migrations/pg/0002_catalog.py +42 -0
  27. nucliadb/ingest/tests/unit/test_settings.py → migrations/pg/0003_catalog_kbid_index.py +5 -3
  28. nucliadb/common/cluster/base.py +41 -24
  29. nucliadb/common/cluster/discovery/base.py +6 -14
  30. nucliadb/common/cluster/discovery/k8s.py +9 -19
  31. nucliadb/common/cluster/discovery/manual.py +1 -3
  32. nucliadb/common/cluster/discovery/single.py +1 -2
  33. nucliadb/common/cluster/discovery/utils.py +1 -3
  34. nucliadb/common/cluster/grpc_node_dummy.py +11 -16
  35. nucliadb/common/cluster/index_node.py +10 -19
  36. nucliadb/common/cluster/manager.py +223 -102
  37. nucliadb/common/cluster/rebalance.py +42 -37
  38. nucliadb/common/cluster/rollover.py +377 -204
  39. nucliadb/common/cluster/settings.py +16 -9
  40. nucliadb/common/cluster/standalone/grpc_node_binding.py +24 -76
  41. nucliadb/common/cluster/standalone/index_node.py +4 -11
  42. nucliadb/common/cluster/standalone/service.py +2 -6
  43. nucliadb/common/cluster/standalone/utils.py +9 -6
  44. nucliadb/common/cluster/utils.py +43 -29
  45. nucliadb/common/constants.py +20 -0
  46. nucliadb/common/context/__init__.py +6 -4
  47. nucliadb/common/context/fastapi.py +8 -5
  48. nucliadb/{tests/knowledgeboxes/__init__.py → common/counters.py} +8 -2
  49. nucliadb/common/datamanagers/__init__.py +24 -5
  50. nucliadb/common/datamanagers/atomic.py +102 -0
  51. nucliadb/common/datamanagers/cluster.py +5 -5
  52. nucliadb/common/datamanagers/entities.py +6 -16
  53. nucliadb/common/datamanagers/fields.py +84 -0
  54. nucliadb/common/datamanagers/kb.py +101 -24
  55. nucliadb/common/datamanagers/labels.py +26 -56
  56. nucliadb/common/datamanagers/processing.py +2 -6
  57. nucliadb/common/datamanagers/resources.py +214 -117
  58. nucliadb/common/datamanagers/rollover.py +77 -16
  59. nucliadb/{ingest/orm → common/datamanagers}/synonyms.py +16 -28
  60. nucliadb/common/datamanagers/utils.py +19 -11
  61. nucliadb/common/datamanagers/vectorsets.py +110 -0
  62. nucliadb/common/external_index_providers/base.py +257 -0
  63. nucliadb/{ingest/tests/unit/test_cache.py → common/external_index_providers/exceptions.py} +9 -8
  64. nucliadb/common/external_index_providers/manager.py +101 -0
  65. nucliadb/common/external_index_providers/pinecone.py +933 -0
  66. nucliadb/common/external_index_providers/settings.py +52 -0
  67. nucliadb/common/http_clients/auth.py +3 -6
  68. nucliadb/common/http_clients/processing.py +6 -11
  69. nucliadb/common/http_clients/utils.py +1 -3
  70. nucliadb/common/ids.py +240 -0
  71. nucliadb/common/locking.py +43 -13
  72. nucliadb/common/maindb/driver.py +11 -35
  73. nucliadb/common/maindb/exceptions.py +6 -6
  74. nucliadb/common/maindb/local.py +22 -9
  75. nucliadb/common/maindb/pg.py +206 -111
  76. nucliadb/common/maindb/utils.py +13 -44
  77. nucliadb/common/models_utils/from_proto.py +479 -0
  78. nucliadb/common/models_utils/to_proto.py +60 -0
  79. nucliadb/common/nidx.py +260 -0
  80. nucliadb/export_import/datamanager.py +25 -19
  81. nucliadb/export_import/exceptions.py +8 -0
  82. nucliadb/export_import/exporter.py +20 -7
  83. nucliadb/export_import/importer.py +6 -11
  84. nucliadb/export_import/models.py +5 -5
  85. nucliadb/export_import/tasks.py +4 -4
  86. nucliadb/export_import/utils.py +94 -54
  87. nucliadb/health.py +1 -3
  88. nucliadb/ingest/app.py +15 -11
  89. nucliadb/ingest/consumer/auditing.py +30 -147
  90. nucliadb/ingest/consumer/consumer.py +96 -52
  91. nucliadb/ingest/consumer/materializer.py +10 -12
  92. nucliadb/ingest/consumer/pull.py +12 -27
  93. nucliadb/ingest/consumer/service.py +20 -19
  94. nucliadb/ingest/consumer/shard_creator.py +7 -14
  95. nucliadb/ingest/consumer/utils.py +1 -3
  96. nucliadb/ingest/fields/base.py +139 -188
  97. nucliadb/ingest/fields/conversation.py +18 -5
  98. nucliadb/ingest/fields/exceptions.py +1 -4
  99. nucliadb/ingest/fields/file.py +7 -25
  100. nucliadb/ingest/fields/link.py +11 -16
  101. nucliadb/ingest/fields/text.py +9 -4
  102. nucliadb/ingest/orm/brain.py +255 -262
  103. nucliadb/ingest/orm/broker_message.py +181 -0
  104. nucliadb/ingest/orm/entities.py +36 -51
  105. nucliadb/ingest/orm/exceptions.py +12 -0
  106. nucliadb/ingest/orm/knowledgebox.py +334 -278
  107. nucliadb/ingest/orm/processor/__init__.py +2 -697
  108. nucliadb/ingest/orm/processor/auditing.py +117 -0
  109. nucliadb/ingest/orm/processor/data_augmentation.py +164 -0
  110. nucliadb/ingest/orm/processor/pgcatalog.py +84 -0
  111. nucliadb/ingest/orm/processor/processor.py +752 -0
  112. nucliadb/ingest/orm/processor/sequence_manager.py +1 -1
  113. nucliadb/ingest/orm/resource.py +280 -520
  114. nucliadb/ingest/orm/utils.py +25 -31
  115. nucliadb/ingest/partitions.py +3 -9
  116. nucliadb/ingest/processing.py +76 -81
  117. nucliadb/ingest/py.typed +0 -0
  118. nucliadb/ingest/serialize.py +37 -173
  119. nucliadb/ingest/service/__init__.py +1 -3
  120. nucliadb/ingest/service/writer.py +186 -577
  121. nucliadb/ingest/settings.py +13 -22
  122. nucliadb/ingest/utils.py +3 -6
  123. nucliadb/learning_proxy.py +264 -51
  124. nucliadb/metrics_exporter.py +30 -19
  125. nucliadb/middleware/__init__.py +1 -3
  126. nucliadb/migrator/command.py +1 -3
  127. nucliadb/migrator/datamanager.py +13 -13
  128. nucliadb/migrator/migrator.py +57 -37
  129. nucliadb/migrator/settings.py +2 -1
  130. nucliadb/migrator/utils.py +18 -10
  131. nucliadb/purge/__init__.py +139 -33
  132. nucliadb/purge/orphan_shards.py +7 -13
  133. nucliadb/reader/__init__.py +1 -3
  134. nucliadb/reader/api/models.py +3 -14
  135. nucliadb/reader/api/v1/__init__.py +0 -1
  136. nucliadb/reader/api/v1/download.py +27 -94
  137. nucliadb/reader/api/v1/export_import.py +4 -4
  138. nucliadb/reader/api/v1/knowledgebox.py +13 -13
  139. nucliadb/reader/api/v1/learning_config.py +8 -12
  140. nucliadb/reader/api/v1/resource.py +67 -93
  141. nucliadb/reader/api/v1/services.py +70 -125
  142. nucliadb/reader/app.py +16 -46
  143. nucliadb/reader/lifecycle.py +18 -4
  144. nucliadb/reader/py.typed +0 -0
  145. nucliadb/reader/reader/notifications.py +10 -31
  146. nucliadb/search/__init__.py +1 -3
  147. nucliadb/search/api/v1/__init__.py +2 -2
  148. nucliadb/search/api/v1/ask.py +112 -0
  149. nucliadb/search/api/v1/catalog.py +184 -0
  150. nucliadb/search/api/v1/feedback.py +17 -25
  151. nucliadb/search/api/v1/find.py +41 -41
  152. nucliadb/search/api/v1/knowledgebox.py +90 -62
  153. nucliadb/search/api/v1/predict_proxy.py +2 -2
  154. nucliadb/search/api/v1/resource/ask.py +66 -117
  155. nucliadb/search/api/v1/resource/search.py +51 -72
  156. nucliadb/search/api/v1/router.py +1 -0
  157. nucliadb/search/api/v1/search.py +50 -197
  158. nucliadb/search/api/v1/suggest.py +40 -54
  159. nucliadb/search/api/v1/summarize.py +9 -5
  160. nucliadb/search/api/v1/utils.py +2 -1
  161. nucliadb/search/app.py +16 -48
  162. nucliadb/search/lifecycle.py +10 -3
  163. nucliadb/search/predict.py +176 -188
  164. nucliadb/search/py.typed +0 -0
  165. nucliadb/search/requesters/utils.py +41 -63
  166. nucliadb/search/search/cache.py +149 -20
  167. nucliadb/search/search/chat/ask.py +918 -0
  168. nucliadb/search/{tests/unit/test_run.py → search/chat/exceptions.py} +14 -13
  169. nucliadb/search/search/chat/images.py +41 -17
  170. nucliadb/search/search/chat/prompt.py +851 -282
  171. nucliadb/search/search/chat/query.py +274 -267
  172. nucliadb/{writer/resource/slug.py → search/search/cut.py} +8 -6
  173. nucliadb/search/search/fetch.py +43 -36
  174. nucliadb/search/search/filters.py +9 -15
  175. nucliadb/search/search/find.py +214 -54
  176. nucliadb/search/search/find_merge.py +408 -391
  177. nucliadb/search/search/hydrator.py +191 -0
  178. nucliadb/search/search/merge.py +198 -234
  179. nucliadb/search/search/metrics.py +73 -2
  180. nucliadb/search/search/paragraphs.py +64 -106
  181. nucliadb/search/search/pgcatalog.py +233 -0
  182. nucliadb/search/search/predict_proxy.py +1 -1
  183. nucliadb/search/search/query.py +386 -257
  184. nucliadb/search/search/query_parser/exceptions.py +22 -0
  185. nucliadb/search/search/query_parser/models.py +101 -0
  186. nucliadb/search/search/query_parser/parser.py +183 -0
  187. nucliadb/search/search/rank_fusion.py +204 -0
  188. nucliadb/search/search/rerankers.py +270 -0
  189. nucliadb/search/search/shards.py +4 -38
  190. nucliadb/search/search/summarize.py +14 -18
  191. nucliadb/search/search/utils.py +27 -4
  192. nucliadb/search/settings.py +15 -1
  193. nucliadb/standalone/api_router.py +4 -10
  194. nucliadb/standalone/app.py +17 -14
  195. nucliadb/standalone/auth.py +7 -21
  196. nucliadb/standalone/config.py +9 -12
  197. nucliadb/standalone/introspect.py +5 -5
  198. nucliadb/standalone/lifecycle.py +26 -25
  199. nucliadb/standalone/migrations.py +58 -0
  200. nucliadb/standalone/purge.py +9 -8
  201. nucliadb/standalone/py.typed +0 -0
  202. nucliadb/standalone/run.py +25 -18
  203. nucliadb/standalone/settings.py +10 -14
  204. nucliadb/standalone/versions.py +15 -5
  205. nucliadb/tasks/consumer.py +8 -12
  206. nucliadb/tasks/producer.py +7 -6
  207. nucliadb/tests/config.py +53 -0
  208. nucliadb/train/__init__.py +1 -3
  209. nucliadb/train/api/utils.py +1 -2
  210. nucliadb/train/api/v1/shards.py +2 -2
  211. nucliadb/train/api/v1/trainset.py +4 -6
  212. nucliadb/train/app.py +14 -47
  213. nucliadb/train/generator.py +10 -19
  214. nucliadb/train/generators/field_classifier.py +7 -19
  215. nucliadb/train/generators/field_streaming.py +156 -0
  216. nucliadb/train/generators/image_classifier.py +12 -18
  217. nucliadb/train/generators/paragraph_classifier.py +5 -9
  218. nucliadb/train/generators/paragraph_streaming.py +6 -9
  219. nucliadb/train/generators/question_answer_streaming.py +19 -20
  220. nucliadb/train/generators/sentence_classifier.py +9 -15
  221. nucliadb/train/generators/token_classifier.py +45 -36
  222. nucliadb/train/generators/utils.py +14 -18
  223. nucliadb/train/lifecycle.py +7 -3
  224. nucliadb/train/nodes.py +23 -32
  225. nucliadb/train/py.typed +0 -0
  226. nucliadb/train/servicer.py +13 -21
  227. nucliadb/train/settings.py +2 -6
  228. nucliadb/train/types.py +13 -10
  229. nucliadb/train/upload.py +3 -6
  230. nucliadb/train/uploader.py +20 -25
  231. nucliadb/train/utils.py +1 -1
  232. nucliadb/writer/__init__.py +1 -3
  233. nucliadb/writer/api/constants.py +0 -5
  234. nucliadb/{ingest/fields/keywordset.py → writer/api/utils.py} +13 -10
  235. nucliadb/writer/api/v1/export_import.py +102 -49
  236. nucliadb/writer/api/v1/field.py +196 -620
  237. nucliadb/writer/api/v1/knowledgebox.py +221 -71
  238. nucliadb/writer/api/v1/learning_config.py +2 -2
  239. nucliadb/writer/api/v1/resource.py +114 -216
  240. nucliadb/writer/api/v1/services.py +64 -132
  241. nucliadb/writer/api/v1/slug.py +61 -0
  242. nucliadb/writer/api/v1/transaction.py +67 -0
  243. nucliadb/writer/api/v1/upload.py +184 -215
  244. nucliadb/writer/app.py +11 -61
  245. nucliadb/writer/back_pressure.py +62 -43
  246. nucliadb/writer/exceptions.py +0 -4
  247. nucliadb/writer/lifecycle.py +21 -15
  248. nucliadb/writer/py.typed +0 -0
  249. nucliadb/writer/resource/audit.py +2 -1
  250. nucliadb/writer/resource/basic.py +48 -62
  251. nucliadb/writer/resource/field.py +45 -135
  252. nucliadb/writer/resource/origin.py +1 -2
  253. nucliadb/writer/settings.py +14 -5
  254. nucliadb/writer/tus/__init__.py +17 -15
  255. nucliadb/writer/tus/azure.py +111 -0
  256. nucliadb/writer/tus/dm.py +17 -5
  257. nucliadb/writer/tus/exceptions.py +1 -3
  258. nucliadb/writer/tus/gcs.py +56 -84
  259. nucliadb/writer/tus/local.py +21 -37
  260. nucliadb/writer/tus/s3.py +28 -68
  261. nucliadb/writer/tus/storage.py +5 -56
  262. nucliadb/writer/vectorsets.py +125 -0
  263. nucliadb-6.2.1.post2777.dist-info/METADATA +148 -0
  264. nucliadb-6.2.1.post2777.dist-info/RECORD +343 -0
  265. {nucliadb-2.46.1.post382.dist-info → nucliadb-6.2.1.post2777.dist-info}/WHEEL +1 -1
  266. nucliadb/common/maindb/redis.py +0 -194
  267. nucliadb/common/maindb/tikv.py +0 -412
  268. nucliadb/ingest/fields/layout.py +0 -58
  269. nucliadb/ingest/tests/conftest.py +0 -30
  270. nucliadb/ingest/tests/fixtures.py +0 -771
  271. nucliadb/ingest/tests/integration/consumer/__init__.py +0 -18
  272. nucliadb/ingest/tests/integration/consumer/test_auditing.py +0 -80
  273. nucliadb/ingest/tests/integration/consumer/test_materializer.py +0 -89
  274. nucliadb/ingest/tests/integration/consumer/test_pull.py +0 -144
  275. nucliadb/ingest/tests/integration/consumer/test_service.py +0 -81
  276. nucliadb/ingest/tests/integration/consumer/test_shard_creator.py +0 -68
  277. nucliadb/ingest/tests/integration/ingest/test_ingest.py +0 -691
  278. nucliadb/ingest/tests/integration/ingest/test_processing_engine.py +0 -95
  279. nucliadb/ingest/tests/integration/ingest/test_relations.py +0 -272
  280. nucliadb/ingest/tests/unit/consumer/__init__.py +0 -18
  281. nucliadb/ingest/tests/unit/consumer/test_auditing.py +0 -140
  282. nucliadb/ingest/tests/unit/consumer/test_consumer.py +0 -69
  283. nucliadb/ingest/tests/unit/consumer/test_pull.py +0 -60
  284. nucliadb/ingest/tests/unit/consumer/test_shard_creator.py +0 -139
  285. nucliadb/ingest/tests/unit/consumer/test_utils.py +0 -67
  286. nucliadb/ingest/tests/unit/orm/__init__.py +0 -19
  287. nucliadb/ingest/tests/unit/orm/test_brain.py +0 -247
  288. nucliadb/ingest/tests/unit/orm/test_processor.py +0 -131
  289. nucliadb/ingest/tests/unit/orm/test_resource.py +0 -275
  290. nucliadb/ingest/tests/unit/test_partitions.py +0 -40
  291. nucliadb/ingest/tests/unit/test_processing.py +0 -171
  292. nucliadb/middleware/transaction.py +0 -117
  293. nucliadb/reader/api/v1/learning_collector.py +0 -63
  294. nucliadb/reader/tests/__init__.py +0 -19
  295. nucliadb/reader/tests/conftest.py +0 -31
  296. nucliadb/reader/tests/fixtures.py +0 -136
  297. nucliadb/reader/tests/test_list_resources.py +0 -75
  298. nucliadb/reader/tests/test_reader_file_download.py +0 -273
  299. nucliadb/reader/tests/test_reader_resource.py +0 -379
  300. nucliadb/reader/tests/test_reader_resource_field.py +0 -219
  301. nucliadb/search/api/v1/chat.py +0 -258
  302. nucliadb/search/api/v1/resource/chat.py +0 -94
  303. nucliadb/search/tests/__init__.py +0 -19
  304. nucliadb/search/tests/conftest.py +0 -33
  305. nucliadb/search/tests/fixtures.py +0 -199
  306. nucliadb/search/tests/node.py +0 -465
  307. nucliadb/search/tests/unit/__init__.py +0 -18
  308. nucliadb/search/tests/unit/api/__init__.py +0 -19
  309. nucliadb/search/tests/unit/api/v1/__init__.py +0 -19
  310. nucliadb/search/tests/unit/api/v1/resource/__init__.py +0 -19
  311. nucliadb/search/tests/unit/api/v1/resource/test_ask.py +0 -67
  312. nucliadb/search/tests/unit/api/v1/resource/test_chat.py +0 -97
  313. nucliadb/search/tests/unit/api/v1/test_chat.py +0 -96
  314. nucliadb/search/tests/unit/api/v1/test_predict_proxy.py +0 -98
  315. nucliadb/search/tests/unit/api/v1/test_summarize.py +0 -93
  316. nucliadb/search/tests/unit/search/__init__.py +0 -18
  317. nucliadb/search/tests/unit/search/requesters/__init__.py +0 -18
  318. nucliadb/search/tests/unit/search/requesters/test_utils.py +0 -210
  319. nucliadb/search/tests/unit/search/search/__init__.py +0 -19
  320. nucliadb/search/tests/unit/search/search/test_shards.py +0 -45
  321. nucliadb/search/tests/unit/search/search/test_utils.py +0 -82
  322. nucliadb/search/tests/unit/search/test_chat_prompt.py +0 -266
  323. nucliadb/search/tests/unit/search/test_fetch.py +0 -108
  324. nucliadb/search/tests/unit/search/test_filters.py +0 -125
  325. nucliadb/search/tests/unit/search/test_paragraphs.py +0 -157
  326. nucliadb/search/tests/unit/search/test_predict_proxy.py +0 -106
  327. nucliadb/search/tests/unit/search/test_query.py +0 -201
  328. nucliadb/search/tests/unit/test_app.py +0 -79
  329. nucliadb/search/tests/unit/test_find_merge.py +0 -112
  330. nucliadb/search/tests/unit/test_merge.py +0 -34
  331. nucliadb/search/tests/unit/test_predict.py +0 -584
  332. nucliadb/standalone/tests/__init__.py +0 -19
  333. nucliadb/standalone/tests/conftest.py +0 -33
  334. nucliadb/standalone/tests/fixtures.py +0 -38
  335. nucliadb/standalone/tests/unit/__init__.py +0 -18
  336. nucliadb/standalone/tests/unit/test_api_router.py +0 -61
  337. nucliadb/standalone/tests/unit/test_auth.py +0 -169
  338. nucliadb/standalone/tests/unit/test_introspect.py +0 -35
  339. nucliadb/standalone/tests/unit/test_versions.py +0 -68
  340. nucliadb/tests/benchmarks/__init__.py +0 -19
  341. nucliadb/tests/benchmarks/test_search.py +0 -99
  342. nucliadb/tests/conftest.py +0 -32
  343. nucliadb/tests/fixtures.py +0 -736
  344. nucliadb/tests/knowledgeboxes/philosophy_books.py +0 -203
  345. nucliadb/tests/knowledgeboxes/ten_dummy_resources.py +0 -109
  346. nucliadb/tests/migrations/__init__.py +0 -19
  347. nucliadb/tests/migrations/test_migration_0017.py +0 -80
  348. nucliadb/tests/tikv.py +0 -240
  349. nucliadb/tests/unit/__init__.py +0 -19
  350. nucliadb/tests/unit/common/__init__.py +0 -19
  351. nucliadb/tests/unit/common/cluster/__init__.py +0 -19
  352. nucliadb/tests/unit/common/cluster/discovery/__init__.py +0 -19
  353. nucliadb/tests/unit/common/cluster/discovery/test_k8s.py +0 -170
  354. nucliadb/tests/unit/common/cluster/standalone/__init__.py +0 -18
  355. nucliadb/tests/unit/common/cluster/standalone/test_service.py +0 -113
  356. nucliadb/tests/unit/common/cluster/standalone/test_utils.py +0 -59
  357. nucliadb/tests/unit/common/cluster/test_cluster.py +0 -399
  358. nucliadb/tests/unit/common/cluster/test_kb_shard_manager.py +0 -178
  359. nucliadb/tests/unit/common/cluster/test_rollover.py +0 -279
  360. nucliadb/tests/unit/common/maindb/__init__.py +0 -18
  361. nucliadb/tests/unit/common/maindb/test_driver.py +0 -127
  362. nucliadb/tests/unit/common/maindb/test_tikv.py +0 -53
  363. nucliadb/tests/unit/common/maindb/test_utils.py +0 -81
  364. nucliadb/tests/unit/common/test_context.py +0 -36
  365. nucliadb/tests/unit/export_import/__init__.py +0 -19
  366. nucliadb/tests/unit/export_import/test_datamanager.py +0 -37
  367. nucliadb/tests/unit/export_import/test_utils.py +0 -294
  368. nucliadb/tests/unit/migrator/__init__.py +0 -19
  369. nucliadb/tests/unit/migrator/test_migrator.py +0 -87
  370. nucliadb/tests/unit/tasks/__init__.py +0 -19
  371. nucliadb/tests/unit/tasks/conftest.py +0 -42
  372. nucliadb/tests/unit/tasks/test_consumer.py +0 -93
  373. nucliadb/tests/unit/tasks/test_producer.py +0 -95
  374. nucliadb/tests/unit/tasks/test_tasks.py +0 -60
  375. nucliadb/tests/unit/test_field_ids.py +0 -49
  376. nucliadb/tests/unit/test_health.py +0 -84
  377. nucliadb/tests/unit/test_kb_slugs.py +0 -54
  378. nucliadb/tests/unit/test_learning_proxy.py +0 -252
  379. nucliadb/tests/unit/test_metrics_exporter.py +0 -77
  380. nucliadb/tests/unit/test_purge.py +0 -138
  381. nucliadb/tests/utils/__init__.py +0 -74
  382. nucliadb/tests/utils/aiohttp_session.py +0 -44
  383. nucliadb/tests/utils/broker_messages/__init__.py +0 -167
  384. nucliadb/tests/utils/broker_messages/fields.py +0 -181
  385. nucliadb/tests/utils/broker_messages/helpers.py +0 -33
  386. nucliadb/tests/utils/entities.py +0 -78
  387. nucliadb/train/api/v1/check.py +0 -60
  388. nucliadb/train/tests/__init__.py +0 -19
  389. nucliadb/train/tests/conftest.py +0 -29
  390. nucliadb/train/tests/fixtures.py +0 -342
  391. nucliadb/train/tests/test_field_classification.py +0 -122
  392. nucliadb/train/tests/test_get_entities.py +0 -80
  393. nucliadb/train/tests/test_get_info.py +0 -51
  394. nucliadb/train/tests/test_get_ontology.py +0 -34
  395. nucliadb/train/tests/test_get_ontology_count.py +0 -63
  396. nucliadb/train/tests/test_image_classification.py +0 -222
  397. nucliadb/train/tests/test_list_fields.py +0 -39
  398. nucliadb/train/tests/test_list_paragraphs.py +0 -73
  399. nucliadb/train/tests/test_list_resources.py +0 -39
  400. nucliadb/train/tests/test_list_sentences.py +0 -71
  401. nucliadb/train/tests/test_paragraph_classification.py +0 -123
  402. nucliadb/train/tests/test_paragraph_streaming.py +0 -118
  403. nucliadb/train/tests/test_question_answer_streaming.py +0 -239
  404. nucliadb/train/tests/test_sentence_classification.py +0 -143
  405. nucliadb/train/tests/test_token_classification.py +0 -136
  406. nucliadb/train/tests/utils.py +0 -108
  407. nucliadb/writer/layouts/__init__.py +0 -51
  408. nucliadb/writer/layouts/v1.py +0 -59
  409. nucliadb/writer/resource/vectors.py +0 -120
  410. nucliadb/writer/tests/__init__.py +0 -19
  411. nucliadb/writer/tests/conftest.py +0 -31
  412. nucliadb/writer/tests/fixtures.py +0 -192
  413. nucliadb/writer/tests/test_fields.py +0 -486
  414. nucliadb/writer/tests/test_files.py +0 -743
  415. nucliadb/writer/tests/test_knowledgebox.py +0 -49
  416. nucliadb/writer/tests/test_reprocess_file_field.py +0 -139
  417. nucliadb/writer/tests/test_resources.py +0 -546
  418. nucliadb/writer/tests/test_service.py +0 -137
  419. nucliadb/writer/tests/test_tus.py +0 -203
  420. nucliadb/writer/tests/utils.py +0 -35
  421. nucliadb/writer/tus/pg.py +0 -125
  422. nucliadb-2.46.1.post382.dist-info/METADATA +0 -134
  423. nucliadb-2.46.1.post382.dist-info/RECORD +0 -451
  424. {nucliadb/ingest/tests → migrations/pg}/__init__.py +0 -0
  425. /nucliadb/{ingest/tests/integration → common/external_index_providers}/__init__.py +0 -0
  426. /nucliadb/{ingest/tests/integration/ingest → common/models_utils}/__init__.py +0 -0
  427. /nucliadb/{ingest/tests/unit → search/search/query_parser}/__init__.py +0 -0
  428. /nucliadb/{ingest/tests → tests}/vectors.py +0 -0
  429. {nucliadb-2.46.1.post382.dist-info → nucliadb-6.2.1.post2777.dist-info}/entry_points.txt +0 -0
  430. {nucliadb-2.46.1.post382.dist-info → nucliadb-6.2.1.post2777.dist-info}/top_level.txt +0 -0
  431. {nucliadb-2.46.1.post382.dist-info → nucliadb-6.2.1.post2777.dist-info}/zip-safe +0 -0
@@ -19,30 +19,17 @@
19
19
  #
20
20
  from fastapi import HTTPException, Response
21
21
  from fastapi_versioning import version
22
- from nucliadb_protos.knowledgebox_pb2 import KnowledgeBoxID
23
- from nucliadb_protos.knowledgebox_pb2 import Label as LabelPB
24
- from nucliadb_protos.knowledgebox_pb2 import LabelSet as LabelSetPB
25
- from nucliadb_protos.writer_pb2 import (
26
- DelEntitiesRequest,
27
- DelLabelsRequest,
28
- DelVectorSetRequest,
29
- NewEntitiesGroupRequest,
30
- NewEntitiesGroupResponse,
31
- OpStatusWriter,
32
- SetLabelsRequest,
33
- SetSynonymsRequest,
34
- UpdateEntitiesGroupRequest,
35
- UpdateEntitiesGroupResponse,
36
- )
37
22
  from starlette.requests import Request
38
23
 
24
+ from nucliadb.common import datamanagers
25
+ from nucliadb.common.datamanagers.exceptions import KnowledgeBoxNotFound
26
+ from nucliadb.common.models_utils import to_proto
39
27
  from nucliadb.models.responses import (
40
28
  HTTPConflict,
41
29
  HTTPInternalServerError,
42
30
  HTTPNotFound,
43
31
  )
44
32
  from nucliadb.writer.api.v1.router import KB_PREFIX, api
45
- from nucliadb.writer.resource.vectors import create_vectorset # type: ignore
46
33
  from nucliadb_models.entities import (
47
34
  CreateEntitiesGroupPayload,
48
35
  UpdateEntitiesGroupPayload,
@@ -50,7 +37,17 @@ from nucliadb_models.entities import (
50
37
  from nucliadb_models.labels import LabelSet
51
38
  from nucliadb_models.resource import NucliaDBRoles
52
39
  from nucliadb_models.synonyms import KnowledgeBoxSynonyms
53
- from nucliadb_models.vectors import VectorSet
40
+ from nucliadb_protos import writer_pb2
41
+ from nucliadb_protos.knowledgebox_pb2 import Label as LabelPB
42
+ from nucliadb_protos.knowledgebox_pb2 import LabelSet as LabelSetPB
43
+ from nucliadb_protos.writer_pb2 import (
44
+ DelEntitiesRequest,
45
+ NewEntitiesGroupRequest,
46
+ NewEntitiesGroupResponse,
47
+ OpStatusWriter,
48
+ UpdateEntitiesGroupRequest,
49
+ UpdateEntitiesGroupResponse,
50
+ )
54
51
  from nucliadb_utils.authentication import requires
55
52
  from nucliadb_utils.utilities import get_ingest
56
53
 
@@ -58,15 +55,13 @@ from nucliadb_utils.utilities import get_ingest
58
55
  @api.post(
59
56
  f"/{KB_PREFIX}/{{kbid}}/entitiesgroups",
60
57
  status_code=200,
61
- name="Create Knowledge Box Entities Group",
58
+ summary="Create Knowledge Box Entities Group",
62
59
  tags=["Knowledge Box Services"],
63
60
  openapi_extra={"x-operation_order": 1},
64
61
  )
65
62
  @requires(NucliaDBRoles.WRITER)
66
63
  @version(1)
67
- async def create_entities_group(
68
- request: Request, kbid: str, item: CreateEntitiesGroupPayload
69
- ):
64
+ async def create_entities_group(request: Request, kbid: str, item: CreateEntitiesGroupPayload):
70
65
  ingest = get_ingest()
71
66
 
72
67
  pbrequest: NewEntitiesGroupRequest = NewEntitiesGroupRequest()
@@ -95,15 +90,13 @@ async def create_entities_group(
95
90
  detail=f"Entities group {item.group} already exists in this Knowledge box",
96
91
  )
97
92
  elif status.status == NewEntitiesGroupResponse.Status.ERROR:
98
- return HTTPInternalServerError(
99
- detail="Error on settings entities on a Knowledge box"
100
- )
93
+ return HTTPInternalServerError(detail="Error on settings entities on a Knowledge box")
101
94
 
102
95
 
103
96
  @api.patch(
104
97
  f"/{KB_PREFIX}/{{kbid}}/entitiesgroup/{{group}}",
105
98
  status_code=200,
106
- name="Update Knowledge Box Entities Group",
99
+ summary="Update Knowledge Box Entities Group",
107
100
  tags=["Knowledge Box Services"],
108
101
  openapi_extra={"x-operation_order": 2},
109
102
  )
@@ -142,15 +135,13 @@ async def update_entities_group(
142
135
  elif status.status == UpdateEntitiesGroupResponse.Status.ENTITIES_GROUP_NOT_FOUND:
143
136
  return HTTPNotFound(detail="Entities group does not exist")
144
137
  elif status.status == UpdateEntitiesGroupResponse.Status.ERROR:
145
- return HTTPInternalServerError(
146
- detail="Error on settings entities on a Knowledge box"
147
- )
138
+ return HTTPInternalServerError(detail="Error on settings entities on a Knowledge box")
148
139
 
149
140
 
150
141
  @api.delete(
151
142
  f"/{KB_PREFIX}/{{kbid}}/entitiesgroup/{{group}}",
152
143
  status_code=200,
153
- name="Delete Knowledge Box Entities",
144
+ summary="Delete Knowledge Box Entities",
154
145
  tags=["Knowledge Box Services"],
155
146
  openapi_extra={"x-operation_order": 3},
156
147
  )
@@ -168,9 +159,7 @@ async def delete_entities(request: Request, kbid: str, group: str):
168
159
  elif status.status == OpStatusWriter.Status.NOTFOUND:
169
160
  raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
170
161
  elif status.status == OpStatusWriter.Status.ERROR:
171
- raise HTTPException(
172
- status_code=500, detail="Error on deleting entities from a Knowledge box"
173
- )
162
+ raise HTTPException(status_code=500, detail="Error on deleting entities from a Knowledge box")
174
163
 
175
164
  return Response(status_code=204)
176
165
 
@@ -178,27 +167,31 @@ async def delete_entities(request: Request, kbid: str, group: str):
178
167
  @api.post(
179
168
  f"/{KB_PREFIX}/{{kbid}}/labelset/{{labelset}}",
180
169
  status_code=200,
181
- name="Set Knowledge Box Labels",
170
+ summary="Set Knowledge Box Labels",
182
171
  tags=["Knowledge Box Services"],
183
172
  openapi_extra={"x-operation_order": 1},
184
173
  )
185
174
  @requires(NucliaDBRoles.WRITER)
186
175
  @version(1)
187
- async def set_labels(request: Request, kbid: str, labelset: str, item: LabelSet):
188
- ingest = get_ingest()
189
- pbrequest: SetLabelsRequest = SetLabelsRequest(id=labelset)
190
- pbrequest.kb.uuid = kbid
191
-
192
- if item.title:
193
- pbrequest.labelset.title = item.title
176
+ async def set_labelset_endpoint(request: Request, kbid: str, labelset: str, item: LabelSet):
177
+ try:
178
+ await set_labelset(kbid, labelset, item)
179
+ except KnowledgeBoxNotFound:
180
+ raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
194
181
 
195
- if item.color:
196
- pbrequest.labelset.color = item.color
197
182
 
198
- pbrequest.labelset.multiple = item.multiple
183
+ async def set_labelset(kbid: str, labelset_id: str, item: LabelSet):
184
+ kb_exists = await datamanagers.atomic.kb.exists_kb(kbid=kbid)
185
+ if not kb_exists:
186
+ raise KnowledgeBoxNotFound()
187
+ labelset = writer_pb2.LabelSet()
188
+ if item.title is not None:
189
+ labelset.title = item.title
190
+ if item.color is not None:
191
+ labelset.color = item.color
192
+ labelset.multiple = item.multiple
199
193
  for kind in item.kind:
200
- pbrequest.labelset.kind.append(LabelSetPB.LabelSetKind.Value(kind))
201
-
194
+ labelset.kind.append(LabelSetPB.LabelSetKind.Value(kind))
202
195
  for label_input in item.labels:
203
196
  lbl = LabelPB()
204
197
  if label_input.uri:
@@ -209,126 +202,65 @@ async def set_labels(request: Request, kbid: str, labelset: str, item: LabelSet)
209
202
  lbl.related = label_input.related
210
203
  if label_input.title:
211
204
  lbl.title = label_input.title
212
- pbrequest.labelset.labels.append(lbl)
213
- status: OpStatusWriter = await ingest.SetLabels(pbrequest) # type: ignore
214
- if status.status == OpStatusWriter.Status.OK:
215
- return None
216
- elif status.status == OpStatusWriter.Status.NOTFOUND:
217
- raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
218
- elif status.status == OpStatusWriter.Status.ERROR:
219
- raise HTTPException(
220
- status_code=500, detail="Error on settings labels on a Knowledge box"
221
- )
205
+ labelset.labels.append(lbl)
206
+ await datamanagers.atomic.labelset.set(kbid=kbid, labelset_id=labelset_id, labelset=labelset)
222
207
 
223
208
 
224
209
  @api.delete(
225
210
  f"/{KB_PREFIX}/{{kbid}}/labelset/{{labelset}}",
226
211
  status_code=200,
227
- name="Delete Knowledge Box Label",
212
+ summary="Delete Knowledge Box Label",
228
213
  tags=["Knowledge Box Services"],
229
214
  openapi_extra={"x-operation_order": 3},
230
215
  )
231
216
  @requires(NucliaDBRoles.WRITER)
232
217
  @version(1)
233
- async def delete_labels(request: Request, kbid: str, labelset: str):
234
- ingest = get_ingest()
235
- pbrequest: DelLabelsRequest = DelLabelsRequest()
236
- pbrequest.kb.uuid = kbid
237
- pbrequest.id = labelset
238
- status: OpStatusWriter = await ingest.DelLabels(pbrequest) # type: ignore
239
- if status.status == OpStatusWriter.Status.OK:
240
- return None
241
- elif status.status == OpStatusWriter.Status.NOTFOUND:
218
+ async def delete_labelset_endpoint(request: Request, kbid: str, labelset: str):
219
+ try:
220
+ await delete_labelset(kbid, labelset)
221
+ except KnowledgeBoxNotFound:
242
222
  raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
243
- elif status.status == OpStatusWriter.Status.ERROR:
244
- raise HTTPException(
245
- status_code=500, detail="Error on deleting labels from a Knowledge box"
246
- )
247
- return Response(status_code=204)
248
-
249
-
250
- @api.post(
251
- f"/{KB_PREFIX}/{{kbid}}/vectorset/{{vectorset}}",
252
- status_code=200,
253
- name="Set Knowledge Box VectorSet",
254
- tags=["Knowledge Box Services"],
255
- openapi_extra={"x-operation_order": 1},
256
- )
257
- @requires(NucliaDBRoles.WRITER)
258
- @version(1)
259
- async def set_vectorset(request: Request, kbid: str, vectorset: str, item: VectorSet):
260
- await create_vectorset(kbid, vectorset, item.dimension, similarity=item.similarity)
261
223
 
262
224
 
263
- @api.delete(
264
- f"/{KB_PREFIX}/{{kbid}}/vectorset/{{vectorset}}",
265
- status_code=200,
266
- name="Delete Knowledge Box VectorSet",
267
- tags=["Knowledge Box Services"],
268
- openapi_extra={"x-operation_order": 3},
269
- )
270
- @requires(NucliaDBRoles.WRITER)
271
- @version(1)
272
- async def delete_vectorset(request: Request, kbid: str, vectorset: str):
273
- ingest = get_ingest()
274
- pbrequest: DelVectorSetRequest = DelVectorSetRequest()
275
- pbrequest.kb.uuid = kbid
276
- pbrequest.vectorset = vectorset
277
- status: OpStatusWriter = await ingest.DelVectorSet(pbrequest) # type: ignore
278
- if status.status == OpStatusWriter.Status.OK:
279
- return None
280
- elif status.status == OpStatusWriter.Status.NOTFOUND:
281
- raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
282
- elif status.status == OpStatusWriter.Status.ERROR:
283
- raise HTTPException(
284
- status_code=500, detail="Error on deleting vectorset from a Knowledge box"
285
- )
286
- return Response(status_code=204)
225
+ async def delete_labelset(kbid: str, labelset_id: str):
226
+ kb_exists = await datamanagers.atomic.kb.exists_kb(kbid=kbid)
227
+ if not kb_exists:
228
+ raise KnowledgeBoxNotFound()
229
+ await datamanagers.atomic.labelset.delete(kbid=kbid, labelset_id=labelset_id)
287
230
 
288
231
 
289
232
  @api.put(
290
233
  f"/{KB_PREFIX}/{{kbid}}/custom-synonyms",
291
234
  status_code=204,
292
- name="Set Knowledge Box Custom Synonyms",
235
+ summary="Set Knowledge Box Custom Synonyms",
293
236
  tags=["Knowledge Box Services"],
294
237
  openapi_extra={"x-operation_order": 1},
295
238
  )
296
239
  @requires(NucliaDBRoles.WRITER)
297
240
  @version(1)
298
241
  async def set_custom_synonyms(request: Request, kbid: str, item: KnowledgeBoxSynonyms):
299
- ingest = get_ingest()
300
- pbrequest = SetSynonymsRequest()
301
- pbrequest.kbid.uuid = kbid
302
- pbrequest.synonyms.CopyFrom(item.to_message())
303
- status: OpStatusWriter = await ingest.SetSynonyms(pbrequest) # type: ignore
304
- if status.status == OpStatusWriter.Status.OK:
305
- return Response(status_code=204)
306
- elif status.status == OpStatusWriter.Status.NOTFOUND:
242
+ if not await datamanagers.atomic.kb.exists_kb(kbid=kbid):
307
243
  raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
308
- elif status.status == OpStatusWriter.Status.ERROR:
309
- raise HTTPException(
310
- status_code=500, detail="Error setting synonyms of a Knowledge box"
311
- )
244
+ synonyms = to_proto.kb_synonyms(item)
245
+ await datamanagers.atomic.synonyms.set(kbid=kbid, synonyms=synonyms)
246
+ return Response(status_code=204)
312
247
 
313
248
 
314
249
  @api.delete(
315
250
  f"/{KB_PREFIX}/{{kbid}}/custom-synonyms",
316
251
  status_code=204,
317
- name="Delete Knowledge Box Custom Synonyms",
252
+ summary="Delete Knowledge Box Custom Synonyms",
318
253
  tags=["Knowledge Box Services"],
319
254
  openapi_extra={"x-operation_order": 3},
320
255
  )
321
256
  @requires(NucliaDBRoles.WRITER)
322
257
  @version(1)
323
258
  async def delete_custom_synonyms(request: Request, kbid: str):
324
- ingest = get_ingest()
325
- pbrequest = KnowledgeBoxID(uuid=kbid)
326
- status: OpStatusWriter = await ingest.DelSynonyms(pbrequest) # type: ignore
327
- if status.status == OpStatusWriter.Status.OK:
328
- return Response(status_code=204)
329
- elif status.status == OpStatusWriter.Status.NOTFOUND:
330
- raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
331
- elif status.status == OpStatusWriter.Status.ERROR:
332
- raise HTTPException(
333
- status_code=500, detail="Error deleting synonyms of a Knowledge box"
334
- )
259
+ async with datamanagers.with_transaction() as txn:
260
+ if not await datamanagers.kb.exists_kb(txn, kbid=kbid):
261
+ raise HTTPException(status_code=404, detail="Knowledge Box does not exist")
262
+
263
+ await datamanagers.synonyms.delete(txn, kbid=kbid)
264
+ await txn.commit()
265
+
266
+ return Response(status_code=204)
@@ -0,0 +1,61 @@
1
+ # Copyright (C) 2021 Bosutech XXI S.L.
2
+ #
3
+ # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
+ # For commercial licensing, contact us at info@nuclia.com.
5
+ #
6
+ # AGPL:
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as
9
+ # published by the Free Software Foundation, either version 3 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+ import contextlib
21
+
22
+ from fastapi import HTTPException
23
+
24
+ from nucliadb.common import datamanagers, locking
25
+
26
+
27
+ @contextlib.asynccontextmanager
28
+ async def noop_context_manager():
29
+ """
30
+ This is used for requests where slug is not set by the user and we don't need to
31
+ care about uniqueness
32
+ """
33
+ yield
34
+
35
+
36
+ @contextlib.asynccontextmanager
37
+ async def ensure_slug_uniqueness(kbid: str, slug: str):
38
+ """
39
+ Make sure slug is unique by:
40
+ - First check if the slug is already taken by another existing resource
41
+ - Otherwise, use the transaction lock to prevent from multiple concurrent
42
+ create resource requests having the same slug.
43
+ """
44
+ try:
45
+ async with locking.distributed_lock(
46
+ key=locking.RESOURCE_CREATION_SLUG_LOCK.format(kbid=kbid, resource_slug=slug),
47
+ # We don't want to wait here. If the lock exists, just raise exception
48
+ lock_timeout=0.0,
49
+ # Matches aprox the max amount of time that the ingest can take
50
+ # to ingest a broker message from the writer.
51
+ expire_timeout=60.0,
52
+ # We don't want to refresh it here
53
+ refresh_timeout=120.0,
54
+ ):
55
+ if await datamanagers.atomic.resources.slug_exists(kbid=kbid, slug=slug):
56
+ raise HTTPException(status_code=409, detail=f"Resource slug {slug} already exists")
57
+ yield
58
+ except locking.ResourceLocked:
59
+ raise HTTPException(
60
+ status_code=409, detail=f"Another resource with the same {slug} is already being ingested"
61
+ )
@@ -0,0 +1,67 @@
1
+ # Copyright (C) 2021 Bosutech XXI S.L.
2
+ #
3
+ # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
+ # For commercial licensing, contact us at info@nuclia.com.
5
+ #
6
+ # AGPL:
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as
9
+ # published by the Free Software Foundation, either version 3 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ import backoff
22
+ from fastapi import HTTPException
23
+
24
+ from nucliadb_protos.writer_pb2 import BrokerMessage
25
+ from nucliadb_utils import const
26
+ from nucliadb_utils.transaction import (
27
+ MaxTransactionSizeExceededError,
28
+ StreamingServerError,
29
+ TransactionCommitTimeoutError,
30
+ )
31
+ from nucliadb_utils.utilities import get_transaction_utility
32
+
33
+
34
+ async def commit(writer: BrokerMessage, partition: int, wait: bool = True) -> None:
35
+ try:
36
+ await transaction_commit(writer, partition, wait)
37
+ except TransactionCommitTimeoutError:
38
+ raise HTTPException(
39
+ status_code=501,
40
+ detail="Inconsistent write. This resource will not be processed and may not be stored.",
41
+ )
42
+ except MaxTransactionSizeExceededError:
43
+ raise HTTPException(
44
+ status_code=413,
45
+ detail="Transaction size exceeded. The resource is too large to be stored. Consider using file fields or split into multiple requests.",
46
+ )
47
+ except StreamingServerError:
48
+ raise HTTPException(
49
+ status_code=504,
50
+ detail="Timeout waiting for the streaming server to respond. Please back off and retry.",
51
+ )
52
+
53
+
54
+ @backoff.on_exception(
55
+ backoff.expo,
56
+ (StreamingServerError,),
57
+ jitter=backoff.random_jitter,
58
+ max_tries=3,
59
+ )
60
+ async def transaction_commit(writer: BrokerMessage, partition: int, wait: bool = True):
61
+ transaction = get_transaction_utility()
62
+ await transaction.commit(
63
+ writer,
64
+ partition,
65
+ wait=wait,
66
+ target_subject=const.Streams.INGEST.subject.format(partition=partition),
67
+ )