31
31
)
32
32
from stac_fastapi .core .extensions import filter
33
33
from stac_fastapi .core .serializers import CollectionSerializer , ItemSerializer
34
- from stac_fastapi .core .utilities import MAX_LIMIT , bbox2polygon
34
+ from stac_fastapi .core .utilities import MAX_LIMIT , bbox2polygon , resolve_refresh
35
35
from stac_fastapi .opensearch .config import (
36
36
AsyncOpensearchSettings as AsyncSearchSettings ,
37
37
)
@@ -864,15 +864,17 @@ def bulk_sync_prep_create_item(
864
864
async def create_item (
865
865
self ,
866
866
item : Item ,
867
- refresh : bool = False ,
868
867
base_url : str = "" ,
869
868
exist_ok : bool = False ,
869
+ ** kwargs : Any ,
870
870
):
871
871
"""Database logic for creating one item.
872
872
873
873
Args:
874
874
item (Item): The item to be created.
875
- refresh (bool, optional): Refresh the index after performing the operation. Defaults to False.
875
+ base_url (str, optional): The base URL for the item. Defaults to an empty string.
876
+ exist_ok (bool, optional): Whether to allow the item to exist already. Defaults to False.
877
+ **kwargs: Additional keyword arguments like refresh.
876
878
877
879
Raises:
878
880
ConflictError: If the item already exists in the database.
@@ -883,6 +885,19 @@ async def create_item(
883
885
# todo: check if collection exists, but cache
884
886
item_id = item ["id" ]
885
887
collection_id = item ["collection" ]
888
+
889
+ # Ensure kwargs is a dictionary
890
+ kwargs = kwargs or {}
891
+
892
+ # Resolve the `refresh` parameter
893
+ refresh = kwargs .get ("refresh" , self .async_settings .database_refresh )
894
+ refresh = resolve_refresh (str (refresh ).lower ())
895
+
896
+ # Log the creation attempt
897
+ logger .info (
898
+ f"Creating item { item_id } in collection { collection_id } with refresh={ refresh } "
899
+ )
900
+
886
901
item = await self .async_prep_create_item (
887
902
item = item , base_url = base_url , exist_ok = exist_ok
888
903
)
@@ -893,19 +908,29 @@ async def create_item(
893
908
refresh = refresh ,
894
909
)
895
910
896
- async def delete_item (
897
- self , item_id : str , collection_id : str , refresh : bool = False
898
- ):
911
+ async def delete_item (self , item_id : str , collection_id : str , ** kwargs : Any ):
899
912
"""Delete a single item from the database.
900
913
901
914
Args:
902
915
item_id (str): The id of the Item to be deleted.
903
916
collection_id (str): The id of the Collection that the Item belongs to.
904
- refresh (bool, optional): Whether to refresh the index after the deletion. Default is False .
917
+ **kwargs: Additional keyword arguments like refresh .
905
918
906
919
Raises:
907
920
NotFoundError: If the Item does not exist in the database.
908
921
"""
922
+ # Ensure kwargs is a dictionary
923
+ kwargs = kwargs or {}
924
+
925
+ # Resolve the `refresh` parameter
926
+ refresh = kwargs .get ("refresh" , self .async_settings .database_refresh )
927
+ refresh = resolve_refresh (str (refresh ).lower ())
928
+
929
+ # Log the deletion attempt
930
+ logger .info (
931
+ f"Deleting item { item_id } from collection { collection_id } with refresh={ refresh } "
932
+ )
933
+
909
934
try :
910
935
await self .client .delete (
911
936
index = index_alias_by_collection_id (collection_id ),
@@ -935,12 +960,12 @@ async def get_items_mapping(self, collection_id: str) -> Dict[str, Any]:
935
960
except exceptions .NotFoundError :
936
961
raise NotFoundError (f"Mapping for index { index_name } not found" )
937
962
938
- async def create_collection (self , collection : Collection , refresh : bool = False ):
963
+ async def create_collection (self , collection : Collection , ** kwargs : Any ):
939
964
"""Create a single collection in the database.
940
965
941
966
Args:
942
967
collection (Collection): The Collection object to be created.
943
- refresh (bool, optional): Whether to refresh the index after the creation. Default is False .
968
+ **kwargs: Additional keyword arguments like refresh .
944
969
945
970
Raises:
946
971
ConflictError: If a Collection with the same id already exists in the database.
@@ -950,6 +975,16 @@ async def create_collection(self, collection: Collection, refresh: bool = False)
950
975
"""
951
976
collection_id = collection ["id" ]
952
977
978
+ # Ensure kwargs is a dictionary
979
+ kwargs = kwargs or {}
980
+
981
+ # Resolve the `refresh` parameter
982
+ refresh = kwargs .get ("refresh" , self .async_settings .database_refresh )
983
+ refresh = resolve_refresh (str (refresh ).lower ())
984
+
985
+ # Log the creation attempt
986
+ logger .info (f"Creating collection { collection_id } with refresh={ refresh } " )
987
+
953
988
if await self .client .exists (index = COLLECTIONS_INDEX , id = collection_id ):
954
989
raise ConflictError (f"Collection { collection_id } already exists" )
955
990
@@ -989,14 +1024,14 @@ async def find_collection(self, collection_id: str) -> Collection:
989
1024
return collection ["_source" ]
990
1025
991
1026
async def update_collection (
992
- self , collection_id : str , collection : Collection , refresh : bool = False
1027
+ self , collection_id : str , collection : Collection , ** kwargs : Any
993
1028
):
994
1029
"""Update a collection from the database.
995
1030
996
1031
Args:
997
- self: The instance of the object calling this function.
998
1032
collection_id (str): The ID of the collection to be updated.
999
1033
collection (Collection): The Collection object to be used for the update.
1034
+ **kwargs: Additional keyword arguments like refresh.
1000
1035
1001
1036
Raises:
1002
1037
NotFoundError: If the collection with the given `collection_id` is not
@@ -1007,9 +1042,23 @@ async def update_collection(
1007
1042
`collection_id` and with the collection specified in the `Collection` object.
1008
1043
If the collection is not found, a `NotFoundError` is raised.
1009
1044
"""
1045
+ # Ensure kwargs is a dictionary
1046
+ kwargs = kwargs or {}
1047
+
1048
+ # Resolve the `refresh` parameter
1049
+ refresh = kwargs .get ("refresh" , self .async_settings .database_refresh )
1050
+ refresh = resolve_refresh (str (refresh ).lower ())
1051
+
1052
+ # Log the update attempt
1053
+ logger .info (f"Updating collection { collection_id } with refresh={ refresh } " )
1054
+
1010
1055
await self .find_collection (collection_id = collection_id )
1011
1056
1012
1057
if collection_id != collection ["id" ]:
1058
+ logger .info (
1059
+ f"Collection ID change detected: { collection_id } -> { collection ['id' ]} "
1060
+ )
1061
+
1013
1062
await self .create_collection (collection , refresh = refresh )
1014
1063
1015
1064
await self .client .reindex (
@@ -1025,7 +1074,7 @@ async def update_collection(
1025
1074
refresh = refresh ,
1026
1075
)
1027
1076
1028
- await self .delete_collection (collection_id )
1077
+ await self .delete_collection (collection_id = collection_id , ** kwargs )
1029
1078
1030
1079
else :
1031
1080
await self .client .index (
@@ -1035,23 +1084,34 @@ async def update_collection(
1035
1084
refresh = refresh ,
1036
1085
)
1037
1086
1038
- async def delete_collection (self , collection_id : str , refresh : bool = False ):
1087
+ async def delete_collection (self , collection_id : str , ** kwargs : Any ):
1039
1088
"""Delete a collection from the database.
1040
1089
1041
1090
Parameters:
1042
1091
self: The instance of the object calling this function.
1043
1092
collection_id (str): The ID of the collection to be deleted.
1044
- refresh (bool): Whether to refresh the index after the deletion (default: False) .
1093
+ **kwargs: Additional keyword arguments like refresh .
1045
1094
1046
1095
Raises:
1047
1096
NotFoundError: If the collection with the given `collection_id` is not found in the database.
1048
1097
1049
1098
Notes:
1050
1099
This function first verifies that the collection with the specified `collection_id` exists in the database, and then
1051
- deletes the collection. If `refresh` is set to True, the index is refreshed after the deletion. Additionally, this
1052
- function also calls `delete_item_index` to delete the index for the items in the collection.
1100
+ deletes the collection. If `refresh` is set to "true", "false", or "wait_for", the index is refreshed accordingly after
1101
+ the deletion. Additionally, this function also calls `delete_item_index` to delete the index for the items in the collection.
1053
1102
"""
1103
+ # Ensure kwargs is a dictionary
1104
+ kwargs = kwargs or {}
1105
+
1054
1106
await self .find_collection (collection_id = collection_id )
1107
+
1108
+ # Resolve the `refresh` parameter
1109
+ refresh = kwargs .get ("refresh" , self .async_settings .database_refresh )
1110
+ refresh = resolve_refresh (str (refresh ).lower ())
1111
+
1112
+ # Log the deletion attempt
1113
+ logger .info (f"Deleting collection { collection_id } with refresh={ refresh } " )
1114
+
1055
1115
await self .client .delete (
1056
1116
index = COLLECTIONS_INDEX , id = collection_id , refresh = refresh
1057
1117
)
@@ -1061,15 +1121,17 @@ async def bulk_async(
1061
1121
self ,
1062
1122
collection_id : str ,
1063
1123
processed_items : List [Item ],
1064
- refresh : bool = False ,
1124
+ ** kwargs : Any ,
1065
1125
) -> Tuple [int , List [Dict [str , Any ]]]:
1066
1126
"""
1067
1127
Perform a bulk insert of items into the database asynchronously.
1068
1128
1069
1129
Args:
1070
1130
collection_id (str): The ID of the collection to which the items belong.
1071
1131
processed_items (List[Item]): A list of `Item` objects to be inserted into the database.
1072
- refresh (bool): Whether to refresh the index after the bulk insert (default: False).
1132
+ **kwargs (Any): Additional keyword arguments, including:
1133
+ - refresh (str, optional): Whether to refresh the index after the bulk insert.
1134
+ Can be "true", "false", or "wait_for". Defaults to the value of `self.sync_settings.database_refresh`.
1073
1135
1074
1136
Returns:
1075
1137
Tuple[int, List[Dict[str, Any]]]: A tuple containing:
@@ -1078,32 +1140,58 @@ async def bulk_async(
1078
1140
1079
1141
Notes:
1080
1142
This function performs a bulk insert of `processed_items` into the database using the specified `collection_id`.
1081
- The insert is performed asynchronously, and the event loop is used to run the operation in a separate executor.
1082
- The `mk_actions` function is called to generate a list of actions for the bulk insert. If `refresh` is set to True,
1083
- the index is refreshed after the bulk insert.
1143
+ The insert is performed synchronously and blocking, meaning that the function does not return until the insert has
1144
+ completed. The `mk_actions` function is called to generate a list of actions for the bulk insert. The `refresh`
1145
+ parameter determines whether the index is refreshed after the bulk insert:
1146
+ - "true": Forces an immediate refresh of the index.
1147
+ - "false": Does not refresh the index immediately (default behavior).
1148
+ - "wait_for": Waits for the next refresh cycle to make the changes visible.
1084
1149
"""
1150
+ # Ensure kwargs is a dictionary
1151
+ kwargs = kwargs or {}
1152
+
1153
+ # Resolve the `refresh` parameter
1154
+ refresh = kwargs .get ("refresh" , self .async_settings .database_refresh )
1155
+ refresh = resolve_refresh (str (refresh ).lower ())
1156
+
1157
+ # Log the bulk insert attempt
1158
+ logger .info (
1159
+ f"Performing bulk insert for collection { collection_id } with refresh={ refresh } "
1160
+ )
1161
+
1162
+ # Handle empty processed_items
1163
+ if not processed_items :
1164
+ logger .warning (f"No items to insert for collection { collection_id } " )
1165
+ return 0 , []
1166
+
1085
1167
raise_on_error = self .async_settings .raise_on_bulk_error
1086
1168
success , errors = await helpers .async_bulk (
1087
1169
self .client ,
1088
1170
mk_actions (collection_id , processed_items ),
1089
1171
refresh = refresh ,
1090
1172
raise_on_error = raise_on_error ,
1091
1173
)
1174
+ # Log the result
1175
+ logger .info (
1176
+ f"Bulk insert completed for collection { collection_id } : { success } successes, { len (errors )} errors"
1177
+ )
1092
1178
return success , errors
1093
1179
1094
1180
def bulk_sync (
1095
1181
self ,
1096
1182
collection_id : str ,
1097
1183
processed_items : List [Item ],
1098
- refresh : bool = False ,
1184
+ ** kwargs : Any ,
1099
1185
) -> Tuple [int , List [Dict [str , Any ]]]:
1100
1186
"""
1101
1187
Perform a bulk insert of items into the database synchronously.
1102
1188
1103
1189
Args:
1104
1190
collection_id (str): The ID of the collection to which the items belong.
1105
1191
processed_items (List[Item]): A list of `Item` objects to be inserted into the database.
1106
- refresh (bool): Whether to refresh the index after the bulk insert (default: False).
1192
+ **kwargs (Any): Additional keyword arguments, including:
1193
+ - refresh (str, optional): Whether to refresh the index after the bulk insert.
1194
+ Can be "true", "false", or "wait_for". Defaults to the value of `self.sync_settings.database_refresh`.
1107
1195
1108
1196
Returns:
1109
1197
Tuple[int, List[Dict[str, Any]]]: A tuple containing:
@@ -1113,9 +1201,29 @@ def bulk_sync(
1113
1201
Notes:
1114
1202
This function performs a bulk insert of `processed_items` into the database using the specified `collection_id`.
1115
1203
The insert is performed synchronously and blocking, meaning that the function does not return until the insert has
1116
- completed. The `mk_actions` function is called to generate a list of actions for the bulk insert. If `refresh` is set to
1117
- True, the index is refreshed after the bulk insert.
1204
+ completed. The `mk_actions` function is called to generate a list of actions for the bulk insert. The `refresh`
1205
+ parameter determines whether the index is refreshed after the bulk insert:
1206
+ - "true": Forces an immediate refresh of the index.
1207
+ - "false": Does not refresh the index immediately (default behavior).
1208
+ - "wait_for": Waits for the next refresh cycle to make the changes visible.
1118
1209
"""
1210
+ # Ensure kwargs is a dictionary
1211
+ kwargs = kwargs or {}
1212
+
1213
+ # Resolve the `refresh` parameter
1214
+ refresh = kwargs .get ("refresh" , self .sync_settings .database_refresh )
1215
+ refresh = resolve_refresh (str (refresh ).lower ())
1216
+
1217
+ # Log the bulk insert attempt
1218
+ logger .info (
1219
+ f"Performing bulk insert for collection { collection_id } with refresh={ refresh } "
1220
+ )
1221
+
1222
+ # Handle empty processed_items
1223
+ if not processed_items :
1224
+ logger .warning (f"No items to insert for collection { collection_id } " )
1225
+ return 0 , []
1226
+
1119
1227
raise_on_error = self .sync_settings .raise_on_bulk_error
1120
1228
success , errors = helpers .bulk (
1121
1229
self .sync_client ,
0 commit comments