stdray: (pic#896193)
[personal profile] stdray
Написал, точнее переписал (процесс продолжается) весь слой загрузки данных из внешних стрёмных источников. Переписал не из чувства прекрасного, а по следующим причинам:
1. целиком и полностью изменилось внутренне представление данных
2. невозможно поддерживать существующий код
3. невозможно анализировать работу существующих процессов загрузки

Я с некоторых пор не любитель писать с нуля, но здесь вынужденно во все тяжкие. И если с первым пунктом все понятно, то про два других подробней. Это про то, почему «написал», а не «переписал».

Пункт 2. Это про то, что импорт данных для некоторых источников (один из которых является для нас ключевым), был написан на аутсорсе. Это ебаные филиалы ада с расширением .cs, с файлами под миллион строк, про которые я ничего сказать не могу. И никто не может, это говно никогда не правилось, но если дело было совсем плохо, то вешались обработчики на высер (результат) этого "модуля".

Пункт 3. Это про состояние. ДАТАВРЕМЯ последнего обработанного элемента — это не состояние. ДАТАВРЕМЯ последнего запуска — это тем более не состояние. НЕ СХОРОНЕНИЕ идентификаторов документов на внешнем источнике, которые мы по каким-то причинам не сумели обработать — это не состояние тоже.

Зачем вообще нужно состояние?
Мне оно нужно чтобы:
а) анализировать работу загрузчиков
б) переобрабатывать, если изменилась логика, не дергая при этом внешний источник
в) не переобрабатывать уже обработанные документы

Важны приоритеты
Не имея представления о том, как идет процесс, невозможно:
- дать оценку объемам загружаемой информации (для многих источников, никакой статистики вроде «сколько всего документов» получить невозможно)
- скорости загрузки данных
Не имея полного кеша уже загруженных документов, невозможно успевать за процессом «дизайна». То есть меняются требования, меняются внутренние схемы данных и надо постоянно репроцессить уже имеющиеся данные, чтобы соответствовать.
«Не переобрабатывать» - это всего лишь оптимизация. Но все наши существующие загрузчики были написаны именно исходя из этого пункта.

Отступление от темы
Надрачивание на пункт (в) объяснимо тем, что многие источники вставляют палки в колеса, вводя разнообразные лимиты на количество параллельных обращений или обращений в единицу времени.
По факту, примитивы вроде:
- локального кеширующего прокси
- зеркала фтп
- тысяч хттп-прокси в разных диапазонах адресов,
стоят что по работе, что по деньгам примерно нихуя, позволяя писать логику загрузки первичных данных влоб.

Что имеем сейчас
а. состояние всех элементов, когда-либо появлявшихся в поле зрения загрузчика
б. локальную копию внешних документов с присоединенной метаинформацией (бизнес-ключи, типы документов, версии, даты публикации, версии схем и тд)
в. состояние обработки документов из локального кеша
г. так называемые «внутренние документы», которые версионируются, давая нам историчность.

Про представление состояния
Для анализа и исправления ошибок, с учетом того, что хоть какие-то данные лучше чем ничего (по бизнесу), я пришел к следующей градации состояний конкретных документов:
- в очереди
- успешно обработан
- частично обработан (есть ошибки)
- ошибка
- нет результата

Поясню два состояния, поскольку остальные очевидны.
«частично обработан (есть ошибки)» используется в случаях, когда «один-много», то есть один внешний документ порождает пачку внутренних (возможно разных типов).
«нет результата» выделен в отдельную категорию, потому что я считаю эту ситуацию исключительной, но случай, когда на руках есть документ, описывающий некоторое изменение над исходным документом, при отсутствии этого самого исходника, вполне рядовой.

Про идентификаторы и «полное состояние»
Я представляю себе процесс загрузки как цикл:
1. getState: void → TState
2. getQueue: TState → Seq[TUri]
3. getDocumetns: Seq[TUri] → Seq[TDocument]
4. updateSatate: TState * Seq[TDocument] → TState
5. saveStateAndDocument: TState * Seq[TDocument] → void
6. goto 1

Идентификатор (TUri) – это любой идентификатор, который только можно найти, чтобы его обработка в любой момент времени давала один и тот же результат. Например для фтп я принимаю за TUri тройку (путь_к_файлу*размер*дата_последней_модификации). К сожалению, построить такой более-менее достоверный идентификатор удается не всегда, но надо к этому стремиться. Даже если для того, чтобы узнать загружали мы это или нет, придется перезагрузить документ целиком, все равно считаем идентификатор (пусть и в виде Sha1 хеша). Надо следить за инвариантами.
Полное состояние — Set(getQueue), то есть полный набор всех элементов, которые когда либо попадали в очередь. Неважно, фетчили мы рсс, обходили ли фтп или дергали веб-сервис. Все что мы смогли получить должно быть сохранено. Если на этапе (3) мы ничего не получим, то либо можно не беспокоиться, либо расследовать инцидент с внешним источником. Срсли, даже если эти штуки указывают в никуда, то енто ни по производительности, ни по памяти не бьет.

Ближе к коду
Состояние можно представить например так http://pastebin.com/D2BhbHcV
Я использую штатный дотнетовский XmlSerializer и сохраняю состояние в XML-поле в БД. Это дает возможность отправлять документы на переобработку (все или какие-то конкретные) одним простым, пусть и ебанутым (так как там xpath) запросом.
Можно было бы использовать словарь и не городить кучу одинакового кода, но я пробовал, и такая структура менее удобна в обращении.



Я вообще-то хотел написать про логирование, но написал про импортирование данных. Видимо, потому, что есть положительный опыт, когда пусть и неочевидным сходу образом, в эту простую концепцию укладываются, казалось бы, несовместимые с ней источники данных.

Как всегда жду критики и всяких отзiвов. Только не надо рассказывать про НИНУЖНАСТЬ всего в виду существования ETL систем. У нас такая в наличии, и весь сыр-бор именно для того, чтобы ента самая система таки сумела взять специально для нее сформированные по схеме данные и разложить по табличкам. ETL, Data Vault, Oracle Enterprise – такие-то базвард колоссы, стоящие на обычном быдлакоде.

August 2017

S M T W T F S
  12345
6789101112
13141516171819
20212223242526
27282930 31  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags