@@ -76,21 +76,23 @@ async def _create_in_batch(
7676 self ,
7777 kind : str ,
7878 data_list : list ,
79+ allow_upsert : bool = False ,
7980 ) -> None :
8081 """
8182 Create objects of a specific kind and store in local store.
8283
8384 Args:
8485 kind: The kind of object to create.
8586 data_list: List of data dictionaries for creation.
87+ allow_upsert: Whether to allow upsert operations. Use False for new devices to prevent race conditions.
8688 """
8789 batch = await self .client .create_batch ()
8890 for data in data_list :
8991 try :
9092 obj = await self .client .create (
9193 kind = kind , data = data .get ("payload" ), branch = self .branch
9294 )
93- batch .add (task = obj .save , allow_upsert = True , node = obj )
95+ batch .add (task = obj .save , allow_upsert = allow_upsert , node = obj )
9496 if data .get ("store_key" ):
9597 self .client .store .set (
9698 key = data .get ("store_key" ), node = obj , branch = self .branch
@@ -110,6 +112,40 @@ async def _create_in_batch(
110112 except ValidationError as exc :
111113 self .log .debug (f"- Creation failed due to { exc } " )
112114
115+ async def _create_sequentially (
116+ self ,
117+ kind : str ,
118+ data_list : list ,
119+ ) -> None :
120+ """
121+ Create objects sequentially (one at a time) with upsert enabled.
122+ This prevents race conditions while maintaining idempotency.
123+
124+ Args:
125+ kind: The kind of object to create.
126+ data_list: List of data dictionaries for creation.
127+ """
128+ for data in data_list :
129+ try :
130+ obj = await self .client .create (
131+ kind = kind , data = data .get ("payload" ), branch = self .branch
132+ )
133+ await obj .save (allow_upsert = True )
134+ if data .get ("store_key" ):
135+ self .client .store .set (
136+ key = data .get ("store_key" ), node = obj , branch = self .branch
137+ )
138+ object_reference = (
139+ " " .join (obj .hfid ) if obj .hfid else obj .display_label
140+ )
141+ self .log .info (
142+ f"- Created [{ obj .get_kind ()} ] { object_reference } "
143+ if object_reference
144+ else f"- Created [{ obj .get_kind ()} ]"
145+ )
146+ except (GraphQLError , ValidationError ) as exc :
147+ self .log .debug (f"- Creation failed due to { exc } " )
148+
113149 async def _create (self , kind : str , data : dict ) -> None :
114150 """
115151 Create an object of a specific kind and store in local store.
@@ -214,6 +250,7 @@ async def create_address_pools(self, subnets: list[dict]) -> None:
214250 }
215251 for pool in subnets
216252 ],
253+ allow_upsert = True ,
217254 )
218255
219256 async def create_split_loopback_pools (self , technical_subnet_obj : Any ) -> None :
@@ -382,7 +419,7 @@ async def create_devices(self) -> None:
382419 ("DcimVirtualDevice" , virtual_devices ),
383420 ]:
384421 if devices :
385- await self ._create_in_batch (kind = kind , data_list = devices )
422+ await self ._create_sequentially (kind = kind , data_list = devices )
386423
387424 self .devices = [
388425 self .client .store .get_by_hfid (f"DcimGenericDevice__{ device [0 ]} " )
0 commit comments