Следующий код работал для меня.
scala> def f[S,D](values: Seq[Map[S, D]]): Map[S,D] = { values.flatten.toMap}
f: [S, D](values: Seq[Map[S,D]])Map[S,D]
scala> val flattenSeqOfMaps = udf { f[String,Double] _}
flattenSeqOfMaps: org.apache.spark.sql.expressions.UserDefinedFunction = UserDefinedFunction(<function1>,MapType(StringType,DoubleType,false),Some(List(ArrayType(MapType(StringType,DoubleType,false),true))))
Так, существует горстка способов сделать то, что Вы спрашиваете. Но большое количество их не будет независимой реализацией: Вы могли использовать блокировки или скалы, но они будут действительно только работать над поточными серверами 100% и вероятно нисколько в fork/pre-fork реализации.
Это более или менее означает, что реализация блокировки будет ваше дело. Две идеи:
.lock
файл в Вашей файловой системеlocked
свойство в Вашем образцовом классеВ обоих случаях необходимо вручную установить объект блокирования на обновлении, и проверка по сравнению с ним на удаляют. Попробуйте что-то как:
def safe_update(request,model,id):
obj = model.objects.get(id)
if obj.locked:
raise SimultaneousUpdateError #Define this somewhere
else:
obj.lock()
return update_object(request,model,id)
# In models file
class SomeModel(models.Model):
locked = models.BooleanField(default = False)
def lock(self):
self.locked = True
super(models.Model,self).save()
def save(self):
# overriding save because you want to use generic views
# probably not the best idea to rework model code to accomodate view shortcuts
# but I like to give examples.
self.locked = False
# THIS CREATES A DIFFERENT CRITICAL REGION!
super(models.Model,self).save()
Это - действительно неуклюжая реализация, которую необходимо будет очистить. Вы не можете быть довольны тем, что другой критический регион был создан, но я не вижу, как Вы сделаете намного лучше если Ваше использование базы данных как реализация, не делая реализацию намного более сложной. (Одна опция состояла бы в том, чтобы сделать совершенно отдельные объекты блокировок. Затем Вы могли обновить их после сохранения (), метод называют. Но я не испытываю желание кодировать это.), Если бы Вы действительно хотите использовать основанную на файле запирающую систему, которая также решила бы проблему. Если Вы - database-hit-paranoid, это могло бы быть вещью для Вас. Что-то как:
class FileLock(object):
def __get__(self,obj):
return os.access(obj.__class__+"_"+obj.id+".lock",os.F_OK)
def __set__(self,obj,value):
if not isinstance(value,bool):
raise AttributeError
if value:
f = open(obj.__class__+"_"+obj.id+".lock")
f.close()
else:
os.remove(obj.__class__+"_"+obj.id+".lock")
def __delete__(self,obj):
raise AttributeError
class SomeModel(models.Model):
locked = FileLock()
def save(self):
super(models.Model,self).save()
self.locked = False
Так или иначе возможно, существует некоторый путь к смешиванию и подгонке эти предложения к Вашему вкусу?
Я предложил бы простую блокировку чтения-записи, поскольку Вы не хотите блокировать пользователей от доступа к объекту одновременно (только от редактирования).
Общий подход к выполнению этого должен был бы создать функцию, которая поддерживает количество активных читателей. Когда необходимо записать в тот объект, Вы создали бы другую функцию, которая будет препятствовать тому, чтобы новые читатели добрались, доступ (думайте страница обслуживания), и возможно перенаправьте существующих читателей далеко. Однажды больше нет оставленных читателей, Вы завершили бы свою запись, затем разблокировали бы объект.
Так как Ваш объем ограничен, удаляет и не также обновляет, одна опция состояла бы в том, чтобы заново продумать идею "удаления" как "неопубликовать" действие. Например, возьмите следующую модель:
class MyManager(models.Manager):
def get_query_set(self):
super(MyManager, self).get_query_set().filter(published=True)
class MyModel(models.Model):
objects = MyManager()
published = models.BooleanField(default=True)
... your fields ...
def my_delete(self):
self.published = False
super(MyModel, self).save()
def save(self):
self.published = True
super(MyModel, self).save()
Таким образом, каждый раз, когда редактирование фиксируется, это видимо всем пользователям..., но другие все еще свободны удалить объекты. Одно преимущество этой техники - Вы, не должны иметь никакой дополнительной логики, чтобы заблокировать объекты и представить другой UI пользователю. Недостатки являются дополнительным пространством, использованным в таблице базы данных и редких обстоятельствах, где удаленный объект "волшебно" вновь появляется.
(Это - вероятно, просто начальная точка. Если бы Вы выбрали это путь, то Вы, вероятно, хотели бы сделать вариацию на эту идею в зависимости от Вашего варианта использования.)