1. даты у нас бывают двух типов: 1) абстрактная дата (день рождения) 2) конкретный момент во времени (время совершения транзакции) Хотелось бы их различать на уровне типов.
1.1. в чем разница?
1.1.1. день рождения нельзя хранить в виде таймстампа (это некая абстрактная цифра, а не момент во времени)
1.1.1.1. отдельный тип
1.2. день рождения может быть строкой
1.2.1. В принципе да, но обычно он связан с возрастом, так что логичнее сделать спец тип.
1.2.1.1. +1
2. правила именования в протоколе
2.1. Использовать единую нотацию для именования полей JSON, чтобы больше не было подобных вещей как два sessionid и sessionId при логине. Пусть везде будет либо camelCase либо underscore_notation
2.2. итого
2.2.1. для сервисов
2.2.2. для доменной модели
2.2.3. для полей запроса ответа
3. автогенерация документации
3.1. автогенерация кода все-таки получше ибо: 1) позволяет генерить код для разных языков. 2) Легко и нативно расширяема, в отличии от кода, который предназначен совсем для другого.
4. проверка инвалидации кешей в compile-time
4.1. Есть два варианта архитектуры, которые решают данную проблему.
4.2. макросы!
4.2.1. макросы - всего-лишь инструмент.
4.2.1.1. который может помочь решить вопрос с меньшими затратами, чем без макросов
4.2.1.1.1. теоретически?:) или ты видишь решение?
4.3. ИТОГО
4.3.1. посмотрим typed-actors. попробуем оттуда утянуть кусок
4.3.2. строковая интерполяция с пакросами
4.3.3. cспереть кусок из https://github.com/kciesielski/macmemo
4.4. избавление от жестких ссылок внутри сервисов/модулей, используемых только для построения правил инвалидации кэшей
4.4.1. Произойдет автоматически при изменении архитектуры
5. каждая операция может иметь клиентский requestId. Если операция вызывается 2й раз с предыдущим requestId, то возвращать результат предыдущей операции
5.1. много памяти под кеш?
5.2. И в каждом респонсе возвращать ИД запросившей операции. В будещем это позволить скореллировать сообщения при работе через вебсокет.
5.3. Не совсем понятно для чего это. Операции бывают двух типов: Команды (с сайд эффектами) и Запросы (данных). Держать результат выполнения Команды в кеше имеет смысл для идемпотентности Команды (если клиент не смог получить ответ, а Команда выполнилась успешно). Но только для последней успешной Команды по конкретному запросу (это много кеша не потребует). Для Запросов requestId смысла вводить не вижу честно говоря.
5.3.1. это плохая практика - принудительное натягивания паттерна request/response на асинхронное взаимодействие. Сокеты дают бОльшие возможности - так давайте ими пользоваться.
5.3.2. Если делать запрос через вебсокет = можно коррелировать запрос-ответ на клиенте. И кроме того можно коррелировать сообщения скажем в смартформе или в создании депозита. Что сейчас некая плохоосознаваемая проблема
5.4. итого
5.4.1. делаем когда будем переносить платежи
5.4.2. только для запросов-команд
5.4.3. делаем ближе к переносу платежей
6. типизация
6.1. единый формат номера мобильного
6.1.1. На вход подается объект разделенный на код страны, номер оператора, номер абоеннта
6.2. даты в читаемом виде (xsd-формат?)
6.2.1. ISO 8601?
6.2.2. Можно расширить сериализацию Time для даты в читабельном виде
6.3. ИТОГО
6.3.1. Даты в схеме прописываем как строки с регекспом
6.3.1.1. пример
6.3.1.1.1. <startdate>2002-05-30T09:30:10+06:00</startdate>
6.4. смещение относительно текущей даты
6.4.1. как в спланке
6.5. дата рождения отдельный тип
6.5.1. от строки
6.5.2. невычисляемый
7. ВСЕ АСИНХРОННОЕ
7.1. асинхронность только там, где нужна.
7.1.1. определается архитектурой и нотациями
8. при переносе удаляем лишние данные из модели.
8.1. Никаких справоччников в запросах с данными
8.1.1. например, в operations не возвращаем всю сущность провайдера
9. Новый конфиг
9.1. все в typesafe config?
9.2. Как
10. механизм лимитов
10.1. модуляризовать
10.2. хочется иметь возможность для каждой апишки иметь свою схему в БД
11. Авторизация основанная на ролях(RSBAC based)
12. Описание сценариев
12.1. Для связи последовательности вызовов хэндлеров одним контекстом
12.2. Для генерации клиентского кода
12.3. Для упрощения автоматического тестирования
12.3.1. Нагрузочные тесты
12.3.2. Регресс тесты
12.3.3. Сервис тесты
13. пинг сессии без ее продления
14. клиент может передавать опциональный ид запроса, который мы вернем в ответе
14.1. необходимо для связи запроса и ответа, например в режиме асинхронной работы с вебсокетами.
14.1.1. для запросов через вебсокеты поле обязательно
15. Сессия в http-onle куке
16. В ядре протокола должен быть флаг аля fallBackData=true|false
17. модуль лимитов
17.1. настраивать стратегии
17.1.1. строгая проверка
17.1.1.1. медленнее
17.1.2. нестрогая проверка
17.1.2.1. быстрее
18. автоматическая сериализация\десериализация ответов и запросов в json, xml без доработок для каждого метода
18.1. маппинг в доменную модель фронта все равно придется где-то прописать
19. мультитранспортность
19.1. вебсокеты
19.2. rest
19.2.1. именно REST, или все-таки HTTP?
19.3. логично сделать абстрактный транспорт, для которого написать различные имплементации
19.3.1. ... или не писать и просто взять акковский стрим
19.3.1.1. при чем тут акковский стрим и абстрактный транспорт?
19.3.1.1.1. при том, что это готовая абстракция высокого уровня, предусматривающая разные бэкэнды для маршаллизации. какую задачу решит наш собственный абстрактный транспорт? даст гипотетическую возможность перескочить с json на protobuff?
19.3.2. Надо доработать хендлер разбив логику на две части: конвертация запроса в кейз-класс с параметрами и собственно работа с кейз классом. Подразумевается что кейзклас полностью определяет ограничения на параметры запроса, в тч формат, обязательность и т.п.
19.3.2.1. "Конвертацию запроса" я называю маппингом из доменной модели фронта в нашу доменную модель. Собственно +1.
19.3.2.2. да, это было бы круто, но как быть с хендлерами, принимающими несколько наборов параметров?
19.3.2.2.1. надо понимать, что отдельный набор параметров это отдельная точка входа - отдельный case class. Вот и все.
19.3.3. Конвертор можно делать как автоматическим (рефлекшн, макросы и т.п) так и нет.
19.3.3.1. рефлекшн - это построение конвертора в рантайме -> тормоза. можно их кэшировать, конечно, но проще сразу взять макросы.
19.3.3.1.1. по умолчанию имплиситный макрос, имплисит можно перекрыть эксплиситом в случае, когда дефолтная десериализация не спасает
19.3.4. Тогда можно часть хендлеров вызывать через веб-сокеты. В принципе если хедлер к такому преобразован - дальше все просто.
19.3.4.1. Логично - если хендлер подготовлен.
19.4. HTTP/2
19.4.1. как только выйдем обновим nginx
19.5. Streaming API a la Twitter - проще, чем websocket
19.5.1. Play Iteratees?
19.5.2. О чем вы вообще говорите - websockets это просто транспорт. WiFi еще круче.
19.5.2.1. ВебСокеты - это как раз-таки протокол. И их реализация достаточно тяжеловесна. Стримы а-ля Твиттер - это по сути незакрывающиеся сокеты с потоком json-объектов, что позволяет гораздо проще переиспользовать JSON-десериализаторы, например.
19.5.2.1.1. хорошо, websocket'ы - это протокол транспортного уровня. Давайте уже отделим транспортный уровень от уровня приложения.
19.5.2.2. Плюс к тому, в стандартах на вебсокеты постоянно ломается обратная совместимость.
19.5.2.2.1. устаревшая информация
19.6. ИТОГО
19.6.1. по вебсокетам делаем и реквест и респонс
19.6.1.1. data оборачиваем в envelop
19.6.1.2. выяснить про безопасность. Овечкин
19.6.1.3. клиент всегда передает requestId, который прлетает еще и в ответе
19.6.1.4. 2 типа ответа Response и Event
19.6.2. берем xml и json
19.6.2.1. для ответов всегда отдельный тип данных Response*
19.6.3. метод для лонгполинга событий если сокеты сдохли
19.6.4. транспорты
19.6.4.1. rest http
19.6.4.1.1. best practive по именован от Овечкина
19.6.4.2. вебсокеты
19.6.5. только сессия в параметрах
19.6.6. v2/object/do/?sessionId=
19.6.6.1. все остальные параметры постом
19.6.6.1.1. отдельные методы можно будет специально разрешать пользовать гетом
19.6.7. Кузьмин говорит, что для них реквесты через сокеты ок
19.6.8. всегда возвращаем 200
20. стандартизация асинхронных событий на фронт
21. единый механизм авторизации
21.1. придумать
21.2. требования от Докучаева
21.2.1. регистрация и авторизация в 1 шаг
21.2.2. ничего 1 в 1 не преносим из v1
21.2.3. signup всегда выолняется с переданной в него сессией
22. запрос пинга без продления жизни сессии
22.1. выдаем сессию только по запросу /session и более никогда не генерить новую
23. схема для описания протокола
23.1. по которой фронты смогут сгенерить код
23.1.1. protobuf?
23.1.2. XSD?
23.1.3. json-schema?
23.1.4. trift?
23.1.5. shacl + json-ld
23.1.6. netflix/falcor
23.1.7. swagger
23.2. надо либо генерить при компиляции, либо аккуратно писать тесты типа ApiJsonTest
23.2.1. один из подходов к генерации схемы, это генерить схему на основе тестов - поскольку в тестах требования к данным и методам очевидно должны быть формализованы в достаточной степени.
23.2.1.1. Спорный подход конечно
23.2.1.2. это будет удобнее \ проще \ стабильнее чем по модели?
23.2.1.2.1. сомнительно
23.3. ИТОГО
23.3.1. JSON-schema
23.3.1.1. jackson
23.3.1.1.1. экстендим своими типами
23.3.1.1.2. аннотации для текста и др
23.3.1.1.3. натравливаем на объект Request и Response
23.3.1.2. пистаь свое на макросах
23.3.1.2.1. todo
23.3.1.3. как-то на тестах автоматом проверялась обратную совместимость. Без написания тестов каждый раз
23.3.1.3.1. пишем сами таск в sbt, который все проверяет, и если не сломалось обновляет правила
24. требования/хотелки
24.1. механизм депрекейшна для нашего API. например, отдавать ответ на запрос в устаревшем формате с искусственной задержкой, чтобы фронт переходил на самую новую версию
24.1.1. бизнес это не одобрит:)
24.1.2. можно возвращать ответ сразу, но с каким-нибудь http кодом, например 405, 403 или 418 :)
24.2. выделение ядря АПИ в модуль для создания отдельных приложений
24.2.1. типа активатора
24.2.2. 2 модуля
24.2.2.1. ядро
24.2.2.2. бизнеслогика
24.3. галочка, чтобы поднимать приложение горячим или холодным
24.3.1. для локального запуска
24.3.2. за счет модулей