Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Марсианская телефония: современные практики в р...

Марсианская телефония: современные практики в разработке приложений на CPaaS Voximplant

From INTERCOM'19
Nov 14, 2019, Moscow

Keywords: Git, Continuous Integration, Continuous Deployment

Avatar for Vladimir Kochnev

Vladimir Kochnev

November 14, 2019

Other Decks in Programming

Transcript

  1. Злые марсиане Делаем продуктовую разработку для стартапов и состоявшихся компаний.

    Все умеем программировать, даже менеджеры. Работаем откуда хотим с 2006 года.
  2. Коммуникация Общаемся текстом в Slack. Созваниваемся голосом в Zoom. Ведем

    длинные обсуждения в Basecamp. Зачем нужен телефон?
  3. Даже у удаленщиков есть офис и телефон Юридическому лицу нужно

    иметь адрес и контактный номер. Телефон нужен, чтобы общаться с внешним миром. Люди всё еще любят звонить по телефону. Есть офис в США: любят, когда можно услышать живого человека. Есть офис в Японии: очень «традиционное» общение, телефон важен.
  4. Нам позвонили! Что делать? Хочется, чтобы человека сразу поприветствовали. Чтобы

    ему хоть кто-нибудь ответил. Постараться не потерять контакт с человеком, если никто не смог ответить.
  5. Мы выбрали VoxImplant Как инженеры, мы хотим максимальную кастомизацию и

    API. Другие облачные сервисы либо ограничены в настройке, либо неудобны для разработки.
  6. Другие решения vs. VoxImplant • Входящий звонок приходит в виде

    HTTP-запроса к твоему серверу. • Ответ нужно сформировать в XML-формате. • Входящий звонок приходит как обычный объект в JS callback. • Как и что отвечать — решает скрипт на JS, выполняемый в облаке. Решение с вебхуками: VoxImplant:
  7. Решение с вебхуками CPaaS Application (user-hosted) HTTP <?xml version="1.0" encoding="UTF-8"?>

    <Response> <Say> Здравствуйте, вы позвонили Злым Марсианам. </Say> </Response> XML
  8. Как мы использовали VoxImplant На звонок отвечает первый доступный менеджер.

    Запись сообщения, если никто не ответил. Каждому менеджеру можно позвонить по его добавочному номеру. Во время разговора звонок можно перенаправить другому менеджеру. Также можно добавить в звонок еще одного собеседника (создать конференцию).
  9. Конфиг.json Ключи для интеграций (email-провайдер, sms-провайдер, etc). Базовый URL, где

    хранятся аудио-клипы. ...и так далее { "country": "RU", "title": "Evil Martians RU", "messenger": { "mandrill": { "apiKey": "123457890ABCDEF" }, }, "baseMsgClipUrl": "https: //site.example.com/clips/ru", ... }
  10. Адресная книга.json Список всех менеджеров хранится в обычном JSON-массиве: [

    { "email": "[email protected]", "ext": "023", "name": "Irina Nazarova", "number": "+79123456789" }, { "email": "[email protected]", "ext": "042", "name": "Maxim Kushner", "number": "+79123456789" }, ... ]
  11. Расписание.json Хранит список только тех менеджеров, которые должны отвечать на

    любой звонок. Можно настроить дни дежурства, временной диапазон, часовой пояс. [ { "email": "[email protected]", "timeZone": "Europe/Moscow", "schedule": { "All": [9, 20], "Sat": false, "Sun": false } }, ... ... { "email": "[email protected]", "timeZone": "Asia/Tel_Aviv", "schedule": { "All": [10, 20] } }, ... ]
  12. Пример: приветствие 1. Проигрываем аудио-клип приветствия. 2. Затем пытаемся осуществить

    дозвон VoxEngine.addEventListener(AppEvents.CallAlerting, e => { let incoming = e.call; incoming.answer(); incoming.startPlayback(config.baseMsgClipUrl + "/hello.mp3"); incoming.addEventListener(CallEvents.PlaybackFinished, () => { callFirstAvailable(); }); });
  13. Пример: дозвон 1. Рекурсивно проходимся по списку менеджеров. 2. Соединяем

    с первым, кто ответил. function callFirstAvailable() { let manager = Schedule.next(); let outgoing = VoxEngine.callPSTN(manager.number, incoming.callerid()); outgoing.addEventListener(CallEvents.Connected, e => { VoxEngine.sendMediaBetween(incoming, outgoing); }); outgoing.addEventListener(CallEvents.Failed, e => { callFirstAvailable(); // recursion lol }); }
  14. Пример: рекордер 1. Ссылка на запись голосового сообщения отправляется нам

    по email и SMS. 2. Провайдеры для отправки Email/SMS могут быть любыми! outgoing.addEventListener(CallEvents.Failed, e => { if (schedule.nonEmpty()) { callFirstAvailable() } else { incoming.record(); incoming.addEventListener(CallEvents.RecordStopped, e => { notifySms(incoming.callerid(), e.url); notifyEmail(incoming.callerid(), e.url); }); } });
  15. Cloud IDE У VoxImplant среда разработки — прямо в браузере.

    Нажимаешь "Save" и код сразу в продакшне!
  16. Ошибки могут быть и в JSON Их сложнее обнаружить: код

    будет запускаться, но всё сломается, когда кто-нибудь позвонит. Хочется как-то валидировать эти данные. [ { "email": "inazarova@evilmartianscom", "timeZone": "Europe/Moscow", "schedule": { "All": [9, 200], "Sat": false, "Sun": false }
  17. Один сценарий — это тяжело :( Хочется хранить конфигурацию отдельно

    от кода. Неудобно работать с большим файлом в 1000 строк. Невозможно разделить работу между несколькими разработчиками.
  18. Поддержка нескольких сценариев Нужно разбить код на несколько сценариев: В

    настройках роутинга VoxImplant можно задать порядок их выполнения:
  19. Поддержка нескольких сценариев Для каждого офиса (RU, US, JP) —

    свой инстанс приложения. У каждого приложения одна и та же кодовая база, но разная конфигурация. Становится тяжело поддерживать настройку набора сценариев для каждого приложения.
  20. Один большой сценарий всё-таки лучше config.ru.json + schedule.ru.json config.us.json +

    schedule.us.json config.jp.json + schedule.jp.json main.js + util.js + + + = bundle.ru.js bundle.us.js bundle.jp.js shared code: configuration: out bundles: Хочется склеить всё в один бандл!
  21. В общем, мы столкнулись с проблемами! Во время активной разработки

    необходимо версионирование кода. Конфигурацию нужно валидировать. Хочется автоматизировать сборку и релиз бандла.
  22. Всё нужно хранить в Git Код и конфигурация — это

    просто файлы в репозитории. Есть версионирование! Изменения нескольких файлов атомарны. Можно положить рядом всякие скрипты.
  23. Скрипты Валидируем конфигурацию (config.ru.json, schedule.ru.json): $ ./bin/validate --office=ru Cтроим бандл:

    $ ./bin/build --office=ru (cat *.ru.json src /*.js > bundle.ru.js) Деплоим при помощи VoxImplant HTTP API: $ ./bin/deploy --office=ru (POST https: //api.voximplant.com/platform_api/AddScenario/)
  24. Pull request-культура Связанные друг с другом изменения собираются в одном

    пулл-реквесте на GitHub. Разработчики могут делать код-ревью друг друга! Менеджеры самостоятельно правят конфигурацию.
  25. Continuous Integration Изменения хочется валидировать автоматически. Релиз новой версии тоже

    хочется автоматизировать. В общем, максимально исключить человеческий фактор.
  26. Circle CI Облачный CI сервис, который интегрируется с GitHub. Реагирует

    на изменения в репозитории (коммиты, пулл- реквесты). Обычно используется для запуска в облаке автоматизированных тестов и сборки.
  27. Заключение Своя автоматизация всегда лучше готовых решений. Писать своё не

    так уж сложно, а ещё это весело! CI-flow не так удобен, как горячая правка файлов в облаке, но он даёт порядок.