Описание работы HMED-M

Демон HMED-M (Mediation) является ядром предбиллинга. Его задачей является обработка поступающих с коллектора разобранных CDR по заданным правилам.

Обработка происходит в процессоре по цепочке фильтров. После завершения обработки результат проверяется валидаторами.

Основные настройки

Помимо общих настроек доступны следующие параметры:

sources:
  amqp:
    mediation:
	  # входная очередь разобранных CDR
      # значение должно совпадать с выходной очередью HMED-C
      consumer: amqp/mediation

destinations:
  amqp:
    ocs:
      # выходная очередь обработанных CDR
      # обработанные CDR передаются в тарификатор (HOCS)
      producer: amqp/ocs
    error:
      # выходная очередь CDR, обработанных с ошибкой
      producer: amqp/error

handlers:
  default:
    destinations:
      # список выходных очередей
      - amqp/ocs
  error:
    destinations:
      # список выходных очередей для CDR, обработанных с ошибкой
      - amqp/error
 
constants:
  # константы, доступные для использования в спецификациях фильтров через переменную $consts
  number_length: 11
  routes: # константа может быть хэшем
    C26052: COMSTAR
    C26053: COMSTAR
  skip_trunks_b: # или массивом
    - C30052
    - C30055
    - C30056
 
workers:
  # список воркеров
  - processor: base/switch # воркер реализует процессор base со спецификацией switch

Настройка фильтров

Пример настройки фильтров:

filters:
 
  # тип фильтра
  set:
    # спецификация фильтра
    short_trunk_a_name:
      # условие выполнения фильтра
      condition: $cdr.trunk_a.like?('^C\d+') # обращение к полю CDR
      field: $trunk_a # установка локальной переменной
      value: $cdr.trunk_a[0:6].upper()
    short_trunk_b_name:
      condition: $cdr.trunk_b.like?('^C\d+')
      field: $trunk_b
      value: $cdr.trunk_b[0:6].upper()
    full_trunk_a_name:
      condition: $trunk_a.empty?()
      field: $trunk_a
      value: $cdr.trunk_a.upper()
    full_trunk_b_name:
      condition: $trunk_b.empty?()
      field: $trunk_b
      value: $cdr.trunk_b.upper()
    route_a_by_trunk_a:
      field: route_a
      value: $const.routes[$trunk_a] or $const.pl_route # использование констант
    route_b_by_trunk_b:
      field: route_b
      value: $const.routes[$trunk_b] or $const.pl_route
    route_b_to_primelink:
      condition: $cdr.route_a != $const.pl_route and $cdr.route_b != $const.pl_route
      field: route_b
      value: $const.pl_route
  replace:
    # Правила замены префиксов по транкам
    station_a_by_trunk:
      # использование локальной переменной $trunk_a, установленной в set-фильтре
      condition: $cdr.station_a.length().in?($const.short_numbers_length) and $trunk_a.in?($const.station_a_replacements_by_trunks)
      field: station_a
      map:
        - '^92144':  '749992244'
        - '^92139':  '749578739'
        - '^921627': '7495797627'
        - '^921389': '7495981389'
        - '^921942': '7495517942'
        - '^921360': '7495741360'
        - '^921701': '7495741701'
        - '^921779': '7495741779'
        - '^921789': '7495741789'
        - '^921195': '7495510195'
        - '^921213': '7495514213'
        - '^921460': '7495600460'
        - '^921470': '7495600470'
        - '^921402': '7495728402'
        - '^921147': '7495730147'
        - '^921988': '7495739988'
        - '^921991': '7495739991'
        - '^921280': '7495580280'
        - '^921080': '7495981080'
        - '^96784':  '749996784'
        - '^44':     '749992244'
        - '^39':     '749578739'
        - '^627':    '7495797627'
        - '^389':    '7495981389'
        - '^1942':   '7495517942'
        - '^360':    '7495741360'
        - '^701':    '7495741701'
        - '^779':    '7495741779'
        - '^789':    '7495741789'
        - '^195':    '7495510195'
        - '^213':    '7495514213'
        - '^460':    '7495600460'
        - '^470':    '7495600470'
        - '^402':    '7495728402'
        - '^147':    '7495730147'
        - '^988':    '7495739988'
        - '^991':    '7495739991'
        - '^280':    '7495580280'
        - '^080':    '7495981080'
    leading_8_in_short_station_a:
      condition: $cdr.station_a.length() == $const.short_number_length
      field: station_a
      map:
        - '^8': 7
    leading_8_in_long_station_b:
      condition: $cdr.station_b.length() >= $const.number_length
      field: station_b
      map:
        - '^8': 7
    leading_8_in_short_station_b:
      condition: $cdr.station_b.length() == $const.short_number_length
      field: station_b
      map:
        - '^8': 7
  if:
    station_a_length_is_7:
      if: $cdr.station_a.length() == 7
      then:
        - if/pl_short_number
    pl_short_number:
      if: $cdr.station_a.starts_with?('922') and $route_a == $const.pl_route # условие
      then:
        # цепочка фильтров в случае выполнения условия
        - prepend/station_a_with('7499')
      else:
	    # цепочка фильтров в случае невыполнения условия
        - replace/station_a_by_trunk
  prepend:
    pl_922_station_a_with_7499:
      condition: $cdr.station_a.length() == 7 and $route_a == $const.pl_route and $cdr.station_a.starts_with?('922')
      field: station_a
      string: 7499
    pl_922_station_b_with_7499:
      condition: $cdr.station_b.length() == 7 and $cdr.station_b.starts_with?('922')
      field: station_b
      string: 7499
    tiny_numbers_in_station_b_with_7495:
      condition: $cdr.station_b.length() == 2 or $cdr.station_b.length() == 3
      field: station_b
      string: 7495

 

Настройка процессоров

processors:
  base:
    # спецификация процессора
    switch:
      # валидатор (тип/спецификация)
      validator: base/main
      # цепочка фильтров
      filters:
        - skip/if_duration_is_0 # тип/спецификация
        - set/short_trunk_a_name
        - set/full_trunk_a_name
        - set/route_a_by_trunk_a
        - replace/dash_in_station_a_with_zeros
        - if/station_a_length_is_7
        - prepend/pl_922_station_a_with_7499
        # в скобках передаются аргументы, доступные в фильтре через переменную $args
		# $args[1] - первый аргумент, $args[2] - второй и т.д.
        - prepend/station_a_with('7495')
        - prepend/station_a_with('7')
        - replace/leading_string_in_station_a('8495', '7495')
        - replace/cut_international_prefix_in_station_b
		  ...
      map:
		# поля выходной CDR, формируемой после обработки
		# эти поля проверяются валидатором
        trunk_a: $cdr.trunk_a
        trunk_b: $cdr.trunk_b
        route_a: $cdr.route_a
        route_b: $cdr.route_b
        station_a: $cdr.station_a
        station_b: $cdr.station_b
        duration_sec: $cdr.duration_sec
        termination_code: $cdr.termination_code
        call_begin: $cdr.call_datetime
        service_code: "'M200'"

Настройка валидации

validators:
  base:
	# спецификация валидатора
    main:
      fields:
        call_begin: # проверяемое поле
          type: float # тип значения (integer - целое число, float - десятичная дробь, string - строка)
          required: true # признак обязательности присутствия поля в CDR
        station_a:
          type: string
          required: true
          length: # проверка длины строки
            min: 11
            max: 15
        service_code:
          type: string
          required: true
          value: M200 # проверка значения (только для строк)
        ...