Нам нужны твои мозги

Хотите расти как разработчик и найти крутую работу? Не протирайте штаны — займитесь Open Source проектами. Так легче всего попасть в лучшие команды разработчиков и положить себе в резюме настоящий проект, вместо нелепых «примеров кода». Но найти подходящий проект для участия сложно. Начинаются лень и отговорки, а за ними — отсутствие профессионального роста, критики по-настоящему крутых программистов, уныние и застой.

На Cult of Martians мы собираем интересные задачи для современных веб-программистов. Можно выбрать подходящую по сложности, продолжительности и специализации. Задачи не выдуманы «из воздуха» — каждая решает насущную проблему, и решить ее можно через создание нового Open Source проекта или улучшение существующего. Решайте задачи, прокачивайтесь, присылайте решение на оценку. Лучших могут пригласить к себе на работу компании, программистам которых понравится ваше решение.

Помощь запрашивает Вова Дем Вова ДемВова Дем

Бэк: Утилита для запуска WebSocket-клиентов с поддержкой сценариев

Для новичков, задача на неделю

Необходимо разработать Ruby-инструмент (CLI) для выполнения сценариев взаимодействия WebSocket-клиентов с сервером.

Утилита может быть использована как для blackbox-тестирования (в том числе и нагрузочного) WebSocket-приложений, так и просто в качестве удобного консольного клиента при разработке.

Польза: возможность применить на практике методы многопоточного программирования, попрактиковаться в написании CLI, поближе познакомиться с технологией WebSocket.

Как это должно работать?

Рассмотрим два примера. Предположим, что наш сервер — это Action Cable.

Пример №1

Предположим, что мы хотим проверить следующий сценарий (echo):

  • клиент отправляет сообщение серверу;

  • сервер в ответ отправляет такое же сообщение клиенту.

Запуск сценария будет производиться так:

$ wsdirector echo.yml ws://localhost:3444/cable

Здесь ws://localhost:3444/echo – путь к нашему WS-приложению, а echo.yml – файл сценария, который может выглядеть так:

# приветственное сообщение от Action Cable
- receive:
    # если поле data – объект, то
    # предполагаем, что это json
    data:
      type: "welcome"
# подписка на канал и ожидание подтверждения
- send:
    data:
      command: "subscribe"
      identifier: "{\"channel\":\"TestChannel\"}"
- receive:
    data:
      type: "subscription_confirmation"
      identifier: "{\"channel\":\"TestChannel\"}"
- send:
    data:
      command: "message"
      identifier: "{\"channel\":\"TestChannel\"}"
      data: "{\"text\": \"echo\",\"action\":\"echo\"}"
- receive:
    data:
      identifier: "{\"channel\":\"TestChannel\"}"
      message: "{\"text\": \"echo\"}"

В случае возникновения ошибки на каком-либо шаге, скрипт должен завершаться с ненулевым статусом (exit code) и выводить в STDERR информацию о том, на каком этапе сценария произошел сбой.

Пример №2

Давайте рассмотрим более интересный случай с несколькими клиентами с отличающимся поведением.

  • все клиенты подключаются к серверу и подписываются на канал;

  • клиенты X отправляют сообщение;

  • все клиенты должны получить такое число сообщений, сколько у нас клиентов X.

Кроме того, нам бы хотелось, чтобы мы могли легко конфигурировать число клиентов:

Наша команда будет выглядеть так:

$ wsdirector -s 10 broadcast.yml ws://localhost:3444/cable

А файл сценария broadcast.yml:

# сценарий публикующего клиента
- client:
    # :scale – это параметр переданный в команде через -s
    # multiplier говорит, сколько нам нужно таких клиентов 
    # (коэффициент "размножения")
    multiplier: ":scale"
    actions:
      # приветственное сообщение от Action Cable
      - receive:
          data:
            type: "welcome"
      # подписка на канал и ожидание подтверждения
      - send:
          data:
            command: "subscribe"
            identifier: "{\"channel\":\"TestChannel\"}"
      - receive:
          data:
            type: "subscription_confirmation"
            identifier: "{\"channel\":\"TestChannel\"}"
      # важный момент – ждём, пока все клиенты достигнут этой точки в сценарии
      - wait_all
      # отправляем сообщение в канал
      - send:
          data:
            command: "message"
            identifier: "{\"channel\":\"TestChannel\"}"
            data: "{\"text\": \"hello\", \"action\":\"broadcast\"}"

# сценарий обычного клиента
- client:
    # слушателей мы хотим в 10 раз больше
    multiplier: ":scale * 10"
    actions:
      # аналогичные действия для подписки на канал пропустим (кстати, как бы нам их переиспользовать?)
      ...
      - wait_all
      - receive:
          # каждый клиент должен получить сообщение от каждого публикующего клиента
          multiplier: ":scale"
          data:
            identifier: "{\"channel\":\"TestChannel\"}"
            message: "{\"text\": \"hello\"}"

Советы по реализации

Язык реализации: Ruby.

Код Action Cable каналов из примеров – gist.

Для реализации веб-сокет клиента можно использовать gem websocket-client-simple, а также посмотреть примеры его использования в Rails или Lite Cable.

Инструкции по выполнению

  1. Форкнуть проект wsdirector на GitHub.
  2. Реализовать необходимый функционал.
  3. Сделать Pull Request.

— Можно мне взять эту задачу?

Все задачи на этой странице еще не решены. Если задача вам интересна — берите и смело делайте. Спрашивать разрешения и становиться в очередь не нужно. Даже если кто-то сделает задачу быстрее вас, не останавливайтесь — ваше решение может быть лучше. Это Open Source!

Помощь запрашивает Эмиль Кашкевич Эмиль КашкевичЭмиль Кашкевич

Бэк: Поддержка Yarn для npmdc

Для новичков, задача на пару дней

Сейчас gem npmdc проверяет наличие установленных npm-пакетов и соответствие их версий на основе файла package.json.

Нужно добавить поддержку Yarn.

Польза: возможность попрактиковаться в программировании на чистом Ruby и написании gem’ов, помочь полезному проекту, который нужен в каждом современном большом Ruby веб-приложении.

Как это работает сейчас:

  1. Разбираем файл package.json и строим по нему дерево зависимостей с указанием версии.
  2. Разбираем содержимое папки node_modules.
  3. Для каждого пакета проверяем его наличие в папке node_modules и соответствие версии, указанной в package.json.
  4. Генерируем отчет и показываем его по завершению операции и/или в процессе выполнения (в зависимости от выбранного formatter’а).

Что нужно сделать:

  1. Добавить в конфиг опцию для выбора пакетного менеджера (NPM/Yarn).
  2. Если выбран Yarn, использовать yarn check:
    • следует предусмотреть отсутствие установленного Yarn;
    • следует предусмотреть путь к исполнительному файлу Yarn на случай, если пользователь планирует использовать глобально установленную версию;
    • вывод отчета проверки yarn check следует привести в соответствие с текущим форматом.
  3. Отобразить используемый пакетный менеджер в сообщениях об ошибках и подсказках.
  4. Добавить тесты.
  5. Добавить информацию о новом функционале в документацию.

Помощь запрашивает Андрей Ситник Андрей СитникАндрей Ситник

Фронт: Событийная архитектура PostCSS

Для продвинутых, задача на месяц

Нужно придумать новый API для плагинов PostCSS — чтобы они все работали вместе, в одном цикле прохода по AST-дереву.

Задание сложное. Оно меньше про код и больше про переговоры, анализ и архитектуру. Но зато дает максимальное количество опыта.

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

Сейчас каждый плагин PostCSS проходит по AST-дереву CSS каждый раз заново. В итоге нельзя делать вложенные функции, и при большом количестве плагинов сильно проседает производительность.

У Babel есть более правильный visitor API: когда плагины подписываются на какие-то типы узлов. А внутри PostCSS запускается один проход по дереву, который в нужных местах дергает подписанные плагины.

Первый этап:

  1. Придумать такой API.
  2. Сделать пару примеров псево-кода: как API будет использоваться в простейших плагинах?
  3. Отправить эти примеры Андрею (Gist или проект на GitHub).

Помощь запрашивает Сергей Долганов Сергей ДолгановСергей Долганов

Бэк: Добавить новые источники данных в Ossert: Reddit

Для уверенных в себе, задача на несколько дней

Нужно добавить в Ossert новые источники данных. Отличным кандидадатом с достаточно богатым API является Reddit.

Это позволит охватить еще один важный аспект развития Open-Source библиотек — доступность и объем поддержки, а также заинтересованность в них.

Польза: возможность научиться работать с API Reddit и узнать больше о метриках и поведении разработчиков свободного ПО.

Как это должно работать?

На данный момент сбор информации уже работает для Rubygems, Github, Bestgems и StackOverflow. Необходимо совместимым образом организовать сбор с новых источников.

Советы по реализации

За основу предлагается взять любой из существующих классов для сбора в Ossert. Например, Ossert::Fetch::Rubygems, и реализовать класс, осуществляющий сбор интересной информации:

module Ossert
  module Fetch
    class Reddit
      def initialize(project)
        ...
      end

      def process
        # Метод сбора основных метрик по проекту
      end
    end
  end
end

Для начала, вам потребуется вникнуть в проблему, решаемую проектом — оценку зрелости свободного ПО.

Для этого нужно проанализировать возможность API вашего источника данных и выбрать:

  1. параметры для сбора;
  2. полезные метрики, которые можно измерить на их основании.

Например:

  • «сколько было комментариев к постам о проекте с момента последнего релиза»;
  • «сколько уникальных пользователей комментировали посты о проекте».

А затем, конечно, организовать сбор этих метрик и параметров.

Инструкции по выполнению

  1. Форкнуть проект Ossert на Github.
  2. Реализовать необходимый функционал.
  3. Сделать Pull Request.

Помощь запрашивает Вова Дем Вова ДемВова Дем

Бэк: Инструмент для тестирования совместимости для AnyCable

Для новичков, задача на неделю

Нужно написать скрипт (и упаковать его в гем), который позволит проводить аттестационное тестирование (от англ. “conformance testing”) приложений-серверов для AnyCable.

Это повысит скорость и удобство разработки новых реализаций серверов, а также поможет поддерживать актуальность текущих реализаций.

Польза: возможность подробно изучить ActionCable и AnyCable, попрактиковаться в написании гемов и написать инструмент, которым будет активно пользоваться сообщество.

Как это должно работать?

Предполагается простой и удобный интерфейс:

$ anycablebility http://localhost:3244/cable

После выполнения каждого сценария в стандартный вывод должна выводится информация вида: название сценария, результат (плюс или минус).

Советы по реализации

Язык реализации: Ruby.

В качестве начальных сценариев для тестирования можно взять приемочные тесты для демо-приложения.

В качестве DSL для написания сценариев и их запуска рекомендуется использовать RSpec.

Для непосредественного взаимодействия с сервером через веб-сокеты можно воспользоваться гемом action_cable_client.

Инструкции по выполнению

  1. Форкнуть проект anycablebility на Гитхабе.
  2. Реализовать необходимый функционал.
  3. Сделать Pull Request.

Помощь запрашивает Сергей Долганов Сергей ДолгановСергей Долганов

Бэк: API Endpoint Sampler

Для уверенных в себе, задача на неделю

Пусть существует Rails приложение с некоторым HTTP API. Будем каждый URL этого API считать эндпоинтом, например:

GET /api/v1/projects/:project_id/notes
GET /api/v1/projects/:project_id/notes/:note_id
POST /api/v2/projects
PUT /api/v3/projects/:project_id

Что хочется получить:

Gem для сбора, просмотра и тэгирования проб (пар запрос/ответ) определенных эндпоинтов HTTP API произвольного Rails-приложения. Тэгом считать произвольную строку.

Что нужно реализовать:

Gem, умеющий следующее:

  • Собирать пробы (пары запрос/ответ) с заданных эндпоинтов, сохранять их в соответствии с правилами:
    • Пробой считать кортеж из:
      • даты-времени;
      • URL запроса;
      • HTTP метода;
      • параметров запроса;
      • тела запроса;
      • тела ответа;
      • набора тэгов.
    • Лимитировать сбор проб: не более Y проб за время X;
    • Автоматически очищать устаревшие пробы по мере получения свежих;
    • Оказывать минимальное влияние на скорость выполнения самого запроса Rails приложением;
    • Хранение организовать на PostgreSQL.
  • Задавать базовую конфигурацию:
    • Ограничение на список эндпоинтов в целом (например, через regexp);
    • Черный список эндпоинтов;
    • Сколько запросов хранить по каждому эндпоинту;
    • Как долго хранить пробу;
    • Сохранять за время X не более Y проб.
  • Конфигурировать обработчики для назначения тегов в момент сбора (например, через lambda функции):

    Sampler.configure do |config|
      config.tag_with "slow", ->(request) { request.time > 200 }
    end
    
  • Просматривать сохраненные пробы, с возможностями:
    • Получения списка доступных эндпоинтов приложения (ограниченных в соответствии с конфигурацией) с количеством имеющихся по ним проб;
    • Получения сводной таблицы проб по эндпоинту с фильтрацией по тэгам (одному или нескольким) (id, timestamp, params, тэги, ссылки на просмотр тела запроса и ответа);
    • Удаления одной или нескольких проб;
    • Просмотра тел запроса и ответа пробы;
  • Устанавливаться в произвольное Rails приложение. Сделать можно, например, так:

    rails generate api:sampler:install