Поддержка офлайна в мобильном приложении презентация

Содержание

Слайд 2

Цель

Поделиться подходом к неблокирующей отправке созданных пользователем данных на сервер

Слайд 3

О чём пойдёт речь

Как «хорошо» отправлять данные на сервер:
концепция
варианты реализации
и ещё пара рецептов

Слайд 4

Чего не будет

Транзакционность

Слайд 5

Интро

Владимир Абакумов, TeamLead ОМР
DIRECTUM и DirectumRX
DIRECTUM Solo и Jazz

Слайд 6

Отправка созданных пользователем данных

Блокируем работу

Слайд 7

Отправка созданных пользователем данных

Блокируем работу
Просто и надежно
Ответственность на пользователе
Бесяче (╯ ° □ °)

╯ (┻━┻) 

Слайд 8

Отправка созданных пользователем данных

Не блокируем работу

Слайд 9

Когда узнаешь, что данные пропали

Слайд 10

Отправка созданных пользователем данных

Не блокируем работу
Не понятен статус

Слайд 11

Отправка созданных пользователем данных

Не блокируем работу
Не понятен статус
Можно потерять данные

Слайд 12

Отправка созданных пользователем данных

Не блокируем работу
Не теряем данные

Слайд 13

Приложение для организации событий

Слайд 14

Приложение для организации событий

Создаём событие, указывая реквизиты, участников
Добавляем фото места
Добавляем новых участников

Слайд 15

Задачи

Создать событие
Добавить фото:
Обработать фото (сжатие, фильтры);
Отправить файл на сервер и получить URL;
Прикрепить к

событию.
Добавить участников

Слайд 16

Схема задач

Слайд 17

Схема задач

Слайд 18

Схема задач

Слайд 19

Схема задач

Слайд 20

Схема задач

Слайд 21

Схема задач

Слайд 22

Схема задач

Слайд 23

Схема задач

Слайд 24

Схема задач

Слайд 25

Схема задач

Слайд 26

Схема задач

Слайд 27

Схема задач

Слайд 28

Схема задач

Слайд 29

Отправка созданных пользователем данных

Разбиваем задачи на атомарные подзадачи
Сохранение данных и состояния задач
Семантически значимый

ключ: EventID_TaskID_SubtaskID
Value в виде примитивных данных или сериализуемых структур, которые переживут изменения из-за обновлений сущностей

Слайд 30

Запросы и их задачи

Request = намерение
RequestTask = как его достичь

Слайд 31

Приложение для организации событий

Создаём событие CreateEventRequest
Добавляем фото места AddPhotoRequest
Добавляем новых участников AddParticipantRequest

Слайд 32

Приложение для организации событий

Request -> RequestTask

Слайд 33

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 34

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 35

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 36

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 37

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 38

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 39

Интерфейс RequestTask

public interface IRequestTask { int Id { get; }
Request Request { get;

}
ExecutingState State { get; } Task RunAsync(); void Load(IReadOnlyDictionary data); IReadOnlyDictionary Save(); }

Слайд 40

Приложение для организации событий

CreateEventRequest CreateEventRequestTask
AddPhotoRequest
CompressPhotoRequestTask
SendPhotoRequestTask
AddPhotoToEventRequestTask
AddParticipantRequest AddParticipantRequestTask

Слайд 41

Очередь

Слайд 42

Очередь

Слайд 43

SerialRequestTask

public class SerialRequestTask : IRequestTask { private readonly IRequestTask _wrappedTask; private readonly IRequestTask _dependingOnTask;


}

Слайд 44

SerialRequestTask

public class SerialRequestTask : IRequestTask { private readonly IRequestTask _wrappedTask; private readonly IRequestTask _dependingOnTask;


}

Слайд 45

SerialRequestTask

public class SerialRequestTask : IRequestTask { private readonly IRequestTask _wrappedTask; private readonly IRequestTask _dependingOnTask;


}

Слайд 46

Очередь

Слайд 47

Очередь

Слайд 48

Очередь

Слайд 49

Очередь

Слайд 50

Очередь

Слайд 51

Очередь

Слайд 52

Очередь

Слайд 53

Очередь

Слайд 54

Очередь

Слайд 55

Очередь

Слайд 56

Очередь

Слайд 57

Очередь

Слайд 58

Очередь

Слайд 59

Очередь

Слайд 60

Очередь

Слайд 61

Очередь

Слайд 62

Очередь

Слайд 63

Очередь

Слайд 64

Очередь

Слайд 65

Очередь

Слайд 66

Очередь

Слайд 67

Очередь

Слайд 68

Очередь

Слайд 69

Очередь

Слайд 70

Очередь

Слайд 71

Очередь

Слайд 72

Очередь

Слайд 73

Очередь

Слайд 74

Очередь

Слайд 75

Преимущества

Удобно разрабатывать
Гарантированная доставка
Просто визуализировать

Слайд 76

Недостатки: сложно

Слайд 77

Недостатки

Необходимость синхронизировать очередь
Сложный, витиеватый код

Слайд 78

И ещё пара рецептов

Слайд 79

Взаимоисключение задач

Слайд 80

Взаимоисключение задач

Слайд 81

Взаимоисключение задач

public class AddParticipantRequest : Request { public int EventId { get; } public

int UserId { get; } public override RequestConnectedType GetConnectedType(Request anotherRequest) => anotherRequest is RemoveParticipantRequest r && r.UserId == UserId ? RequestConnectedType.MutuallyExclusive : base.GetConnectedType(anotherRequest); }

Слайд 82

Взаимоисключение задач

public class AddParticipantRequest : Request { public int EventId { get; } public

int UserId { get; } public override RequestConnectedType GetConnectedType(Request anotherRequest) => anotherRequest is RemoveParticipantRequest r && r.UserId == UserId ? RequestConnectedType.MutuallyExclusive : base.GetConnectedType(anotherRequest); }

Слайд 83

Взаимоисключение задач

public class AddParticipantRequest : Request { public int EventId { get; } public

int UserId { get; } public override RequestConnectedType GetConnectedType(Request anotherRequest) => anotherRequest is RemoveParticipantRequest r && r.UserId == UserId ? RequestConnectedType.MutuallyExclusive : base.GetConnectedType(anotherRequest); }

Слайд 84

Взаимоисключение задач

public class AddParticipantRequest : Request { public int EventId { get; } public

int UserId { get; } public override RequestConnectedType GetConnectedType(Request anotherRequest) => anotherRequest is RemoveParticipantRequest r && r.UserId == UserId ? RequestConnectedType.MutuallyExclusive : base.GetConnectedType(anotherRequest); }

Слайд 85

Взаимоисключение задач

public class AddParticipantRequest : Request { public int EventId { get; } public

int UserId { get; } public override RequestConnectedType GetConnectedType(Request anotherRequest) => anotherRequest is RemoveParticipantRequest r && r.UserId == UserId ? RequestConnectedType.MutuallyExclusive : base.GetConnectedType(anotherRequest); }

Слайд 86

Взаимоисключение задач

Слайд 87

Взаимоисключение задач

Слайд 88

Дедупликация данных

Слайд 89

Дедупликация данных

Слайд 90

Дедупликация данных

Слайд 91

Дедупликация данных

Слайд 92

Дедупликация данных

Слайд 93

Дедупликация данных

Слайд 94

Дедупликация данных

RequestId

Слайд 95

Дедупликация данных

RequestId

RequestId

Слайд 96

Итоги

Разбиваем задачи на атомарные подзадачи
Сохранение и восстановление данных и состояния
Связанные задачи выполняем последовательно
Приоритеты

задач
Взаимоисключение задач
Отправка RequestID на сервер и кэширование результата запроса на сервере по этому RequestID
Имя файла: Поддержка-офлайна-в-мобильном-приложении.pptx
Количество просмотров: 80
Количество скачиваний: 0