def bulk_update(
self,
objs: list[Any],
fields: list[str] | tuple[str, ...],
**kwargs: Any,
) -> int:
if _is_bypassed():
return super().bulk_update(objs, fields, **kwargs)
if not objs:
return super().bulk_update(objs, fields, **kwargs)
syncable = [
instance for instance in objs
if hasattr(instance, 'get_syncable_field_names')
]
if not syncable:
return super().bulk_update(objs, fields, **kwargs)
from django_spire.contrib.sync.django.sequence import ( # noqa: PLC0415
SyncSequenceAllocator,
)
clock = self.model.get_clock()
attname_map = _relation_attname_map(self.model)
field_set = set(fields)
stamped_fields = list(field_set | {
'sync_field_last_modified',
'sync_field_origin_node',
'sync_field_sequence',
'sync_field_timestamps',
})
with transaction.atomic(using=self.db):
sequence_first = SyncSequenceAllocator(using=self.db).allocate(len(syncable)).value_first
sequence_next = sequence_first
for instance in syncable:
now = clock.now()
timestamps = dict(instance.sync_field_timestamps)
for name in field_set:
if name in instance._sync_exclude_fields:
continue
timestamps[attname_map.get(name, name)] = now
instance.sync_field_timestamps = timestamps
instance.sync_field_last_modified = now
instance.sync_field_sequence = sequence_next
instance.sync_field_origin_node = ''
sequence_next += 1
return super().bulk_update(objs, stamped_fields, **kwargs)