Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

+1 183новые вакансии за сутки·93 833вакансии открыты сейчас·Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 273
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 409 кандидатов открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 230
  • Облачные технологии14 171
  • QA вакансии3 456
  • Backend вакансии2 115
  • Инженер данных1 801
  • Продакт-менеджер1 247

Разработка

  • Android1 858
  • iOS1 698
  • Fullstack вакансии996
  • AI вакансии955
  • Frontend вакансии755
  • Mobile вакансии44

По стеку

  • Go8 752
  • Java6 593
  • Node.js2 036
  • .NET1 739
  • Kotlin1 618
  • Rust1 472
  • C#717
  • PHP690
  • C++579

DevOps и инфраструктура

  • Kubernetes7 787
  • DevOps вакансии6 095
  • Linux-инфраструктура5 508
  • Terraform / IaC4 287
  • CI/CD3 272
  • Мониторинг и Observability1 792
  • SRE566
  • Кибербезопасность454

Аналитика и данные

  • Data Scientist1 138
  • Бизнес-аналитик921
  • Аналитик данных858
  • Системный аналитик154

Другие направления

  • Проджект-менеджер624
  • UI/UX дизайн149
  • Ручное тестирование14

По регионам

  • Вакансии в США44 166
  • Вакансии в Европе24 014
  • Вакансии в Канаде4 535
  • Работа в России3 867

По формату

  • Удалённые вакансии75 005
  • Релокация в США44 166
  • Гибридная работа12 485
  • Офисная работа7 090

По уровню

  • Senior вакансии42 643
  • Middle вакансии20 960
  • Junior вакансии6 708

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis38 вакансий
  • Spotify37 вакансий
  • Adyen29 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме ElixirВсе вопросы
ElixirMiddleТеория

Что такое Elixir Agents и когда их использовать вместо GenServer?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Agent — обёртка над GenServer для хранения состояния без кастомной логики сообщений. Когда нужны кастомные handle_call/handle_cast, таймауты, handle_info или сложный lifecycle — используйте GenServer напрямую.

Agent: когда и как

Используйте Agent, когда процесс — это просто хранилище данных с простыми операциями чтения/записи.

defmodule Counter do
  def start_link(initial \\ 0) do
    Agent.start_link(fn -> initial end, name: __MODULE__)
  end

  def increment do
    Agent.update(__MODULE__, &(&1 + 1))
  end

  def value do
    Agent.get(__MODULE__, & &1)
  end
end

# Использование
{:ok, _pid} = Counter.start_link(0)
Counter.increment()
Counter.increment()
IO.inspect(Counter.value())  # => 2

Agent.get/2 — синхронный вызов (call), Agent.update/2 тоже синхронный. Есть Agent.cast/2 для асинхронных обновлений без ожидания ответа. Функция, переданная в Agent, выполняется внутри процесса-агента — длинные вычисления заблокируют всех вызывающих.

Agent vs GenServer: в чём разница

Agent — это тонкая абстракция над GenServer, предназначенная исключительно для управления состоянием. Он скрывает шаблонный код: вам не нужно объявлять init/1, handle_call/3 и handle_cast/2 — достаточно передать функцию-трансформер состояния. GenServer даёт полный контроль над протоколом сообщений, lifecycle и обработкой ошибок.

GenServer: когда и как

Используйте GenServer, когда нужны:

  • Кастомные сообщения через handle_info/2 (например, :timeout, сигналы от других процессов)
  • Разные типы запросов с разной логикой (handle_call vs handle_cast)
  • Инициализация с побочными эффектами (подключение к БД, подписка на события)
  • Тонкая обработка ошибок: {:stop, reason, state}
  • Совместимость с :sys.get_state/1 для отладки
defmodule RateLimiter do
  use GenServer

  @window_ms 60_000
  @max_requests 100

  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  def allow?(client_id) do
    GenServer.call(__MODULE__, {:check, client_id})
  end

  ## Callbacks

  @impl true
  def init(_opts) do
    # Периодически сбрасываем счётчики
    schedule_reset()
    {:ok, %{}}
  end

  @impl true
  def handle_call({:check, client_id}, _from, state) do
    count = Map.get(state, client_id, 0)
    if count < @max_requests do
      {:reply, true, Map.put(state, client_id, count + 1)}
    else
      {:reply, false, state}
    end
  end

  @impl true
  def handle_info(:reset, _state) do
    schedule_reset()
    {:noreply, %{}}  # Сбрасываем все счётчики
  end

  defp schedule_reset do
    Process.send_after(self(), :reset, @window_ms)
  end
end

Здесь handle_info(:reset, ...) обрабатывает сообщение от таймера — это невозможно реализовать через Agent.

Правило выбора

КритерийAgentGenServer
Только хранение состояния✓избыточно
Кастомные сообщения / handle_info✗✓
Инициализация с побочными эффектами✗✓
Разные типы запросов✗✓
Простой счётчик / кэш / аккумулятор✓✓

На практике: если через месяц понадобится добавить handle_info — придётся переписывать Agent в GenServer. Если логика уже нетривиальна, сразу пишите GenServer.

Supervision

Оба модуля одинаково хорошо живут под Supervisor. Agent.child_spec/1 генерируется автоматически, для GenServer — тоже, если определён start_link/1:

children = [
  Counter,           # Agent
  RateLimiter        # GenServer
]
Supervisor.start_link(children, strategy: :one_for_one)

Подводные камни

  • Долгие вычисления в Agent.get/2 — функция выполняется в процессе агента, блокируя других вызывающих. Для тяжёлых операций используйте Agent.get_and_update/2 или переходите на GenServer с явным копированием состояния на сторону клиента.
  • Agent не поддерживает handle_info — сообщения от Process.send_after/3, мониторов или связанных процессов будут проигнорированы или упадут с ошибкой.
  • Отладка Agent сложнее — :sys.get_state/1 работает, но нет возможности подключить кастомный format_status/2 для структурированного вывода.
  • Анонимные агенты теряются — если не передать name:, ссылку на PID нужно хранить самостоятельно. После рестарта супервизора PID меняется.
  • Гонка в get + update — последовательность Agent.get → Agent.update не атомарна. Используйте Agent.get_and_update/2 для атомарных операций «прочитать и изменить».
  • Переусложнённый Agent — признак неправильной абстракции — если в Agent накапливается бизнес-логика, это сигнал перейти на GenServer с явными callback-функциями.
  • Не путайте с Elixir Task — Task для одноразовых асинхронных вычислений, Agent для долгоживущего состояния. Нередко новички используют Agent там, где достаточно Task.async/await.
  • ETS как альтернатива — для высококонкурентного чтения (тысячи процессов одновременно) :ets с режимом :read_concurrency быстрее, чем любой агент, поскольку исключает bottleneck единственного процесса.

Частые вопросы на собеседовании

  • В чём разница между spawn, Task и GenServer для выполнения конкурентного кода?
  • Что такое pattern matching в Elixir и как он используется в ветвях функций (function clauses)?
  • В чём разница между модулем и структурой (struct) в Elixir?
  • Что такое иммутабельность в Elixir и почему она важна для параллелизма?

Типичные ошибки

  • Сводить agents vs genserver к названию метода без lifecycle и failure path.
  • Игнорировать модель runtime: Elixir компилируется в BEAM bytecode и наследует процессы, message passing, supervision и hot-code friendly модель Erlang VM.
  • Не отделять validation, authorization, transaction boundary и business logic.
  • Менять похожие API местами без учёта семантики ошибок и ownership.

Что проверяет интервьюер

  • Объясняет agents vs genserver через конкретную точку lifecycle в Elixir.
  • Приводит корректный минимальный пример без вымышленных методов или callbacks.
  • Называет edge cases: пустые значения, ошибки, транзакции, безопасность или concurrency.

Как вы знаете этот вопрос?

Проверить себя по теме Elixir →

Источники

  • https://hexdocs.pm/elixir/Agent.html
  • https://hexdocs.pm/elixir/
←Предыдущий вопросКак работает pattern matching с конструкциями `case`, `cond` и `with`?Следующий вопрос→Расскажите о случае, когда особенности Elixir повлияли на архитектурное решение, производительность или сопровождение проекта.

Связанные темы

ElixirBackend-Engineeringconcurrencyelixir-ecosystemreliability

Вакансии с этим навыком

  • Automation QA Engineer (Payments)