Skip to Content

Контрамоция

Баг, значицца, у них. То есть, у нас. То есть, еще конкретнее: баг у меня. Это я наш банк в систему CLS вводила, будь она неладна. Вот, говорят. Сделка была должна пройти, как CLS. А она как CLS не прошла. Безобразие. 

Ай-яй-яй. 
Смотрю лог для начала. Пишет моя собственная процедура:
“Deal number XXXXXXX is not CLS because Cut of time is not OK”
Ах, как я люблю эти штучки с Cut of time!
Если моя процедура такое пишет, это значит, что сделка отскочила на самом последнем этапе. Уже известно, что сделка NOSTRO, на приемлемую дату, не в тот же день, DELIVERY, что банк-клиент имеет CLS доступ на момент совершения сделки, и обе валюты, в ней участвующие, тоже. А поскольку процедура этим всем не удовлетворилась, и вошла в эту ебаную вилку проверки времени, то ясно, что, с точки зрения системы, сделка идет НА ЗАВТРА, то бишь, на следующий рабочий день. С точки зрения дилера, сделка должна быть CLS. А система почему-то рассудила иначе. Система, которую я САМА писала. Я ей доверяю. Логическую ошибку самонадеянно исключаю. На корню. 

Ну, покажите мне эту, блядь, сделку!!!


Так. Тип сделки: НОЛЬ. Тупо смотрю на этот нолик. Действительно, не CLS.

Время запоминания: 16 марта 23 часа 51 минута 28 секунд. Они что, охуели там совсем окончательно????? Кто это сделки делает в 12 ночи?????
Время прохода сделки через баланс: 23 часа 49 минут 31 секунда.
КАК ЭТО?????……….
Долго тупо думаю, как может быть такое, что сделка запомнена ПОЗЖЕ, чем баланс ее внес в позицию. Если в сделку вносятся изменения, то система, по идее, ее не трогает, а записывает вместо нее строго обратную сделку с установленным флажком «отмена», а затем вносит измененные данные как третью, новую сделку. 
Через баланс проходят все три, в течение минуты после запоминания. Соответственно, время прохода через баланс должно быть чуточку позже времени запоминания. Если только не было дополнительного апдэйта… 

Смотрю снова в лог. Вижу свою сделку с ремаркой моей процедуры. Вижу ее ДВА РАЗА!!!!! Глазки уже совсем вылезают. 


Иду в код формы, вносящей сделки. Это самая тяжелая форма системы. В ней почти 13 тысяч строк. Она написана длиннющими, нечитаемыми простынями, в которых границы вилки или цикла невозможно отловить, к тому же в ряде мест без соблюдения отступов. Огромные процедуры подписаны прямо под навигационными событиями контролей и часто дублируют друг друга в цикле. Тому, кто такое исходно сделал, нужно засунуть мышку в одно из нижних отверстий тела – в назидание потомству, оторвать руки по плечо и запретить близко подходить к компьютеру. Но на переписывание банк денег не дает.

За время существования в этой форме гуляла рота программистов, включая меня: дописывали бесконечно разрастающуюся функциональность. Никто на свете не знает точно, что и как делает эта форма. Только некоторые из нас знакомы с некоторыми кусочками ее, не более того. 

Ковыряясь в полотенечной длины процедурах запоминания сделок, обнаруживаю: есть два или три (из семидесяти) ерундовых поля, изменения в которых НЕ ПОВЛЕКУТ полноценную рутину замены сделки, а приведут всего лишь к локальному апдейту с изменением даты. 
Значит, именно это и произошло. То, что дилер КОЗЕЛЛЛЛЛЛЛ!!!!! - не криминал. Я всегда могу узнать исходное время сделки, поглядев на дату транзакции. Эта дата дается ИСХОДНОЙ, самой первой сделке, ОДИН РАЗ при запоминании, и больше никогда не меняется. Дата транзакции…

...ЧТО-О-О-О???????


...Я так, ребята, заикаться начну… 


...У сделки, принятой уже балансом в позицию 16 марта в 23 часа 49 минут, время исходной транзакции… 17 марта, ноль часов восемь минут и 26 секунд. О как!!!!! О как!!!! Ни хуя себе!!!!!!!…..


Если бы я курила, я бы пошла это дело перекурить. А так пришлось налить себе шоко и усесться разглядывать снова эту диковинную транзакцию. У нее оказался не NULL номер! Это значило, что сделка ХХХХХХ8 уже сама по себе была апдэйтом некой иной сделки с указанным номером ХХХХХХ5. Я открыла их вместе, пятую и восьмую. Они были похожи, как близнецы-братья: пятая сделка была запомнена 16 же марта на 9 минут раньше восьмой, баланс ее принял на 7 минут раньше восьмой, а время транзакции, которое, по идее, для исходной сделки должно было быть равно времени запоминания, нагло содержало сакраментальное 17 марта ноль часов восемь минут 26 секунд…

 
И тут я обнаружила вещь, от которой опять едва не свалилась со стула. ПЯТАЯ, исходная, сделка - преспокойно прошла как CLS!!!

…………………………………………………………………………………………………………………

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

Потом решила забыть пока про пятую сделку и какая между ними разница, и разобраться сначала по-простому с восьмой: что за диковинная транзакция, случившаяся НА ПОЛЧАСА ПОЗЖЕ ее обработки в балансе (езда на еще не купленной машине, кормление еще не родившегося ребенка), и почему она не CLS. 

Начнем c ovo, так сказать. Как пишутся даты в таблицу сделок?

Время запоминания (апдейта) ставит автоматом SQL-server. В балансе то же самое. В этих полях стоит время базы, время сервера. Время же транзакции…

А вот время транзакции приходит-таки из формы! Это время клиентское, время локального компьютера.
Если проверить по логу, что пятая сделка не перезапоминалась, как восьмая, с мелким локальным апдэйтом, можно предположить, что компьютер дилера убегал по времени вперед от сервера на величину, равную разнице между временем запоминания исходной сделки (16 марта 23:42) и временем исходной транзакции (17 марта 00:08), которые у данной сделки должны были обозначать один и тот же момент времени. Итого 26 минут.


И на кой хуй мне это надо? А не знаю. Так просто. Красивое четное число. Прекрасный возраст для женщины… :))


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

Я не знаю, как они при этом договариваются с CLS, но для меня это означает, что система имеет дело как раз с тем временем, которое вносится со сделкой. Мне же и проще. 


Я нахожу в процедуре нужную мне роковую вилку и выношу ее отдельным скриптом в родной development сервер. Здесь я могу EXECUTE встроенные процедуры и функции. Пробую симулировать то, что произошло ночью.


Итак, процедура принимает в качестве параметров дату\время своего вызова и дату, на которую сделана сделка (чтобы не путаться в словах, назовем ее ДАТА ВЫПОЛНЕНИЯ).

Дата вызова у нас, если какие-нибудь извращенцы помнят, пришедшее со спешащего в будущее локального компьютера now - 17 марта 00:08.

А какая дата выполнения? 18 марта. Правильно: если было бы раньше, сделка НА ТОТ ЖЕ ДЕНЬ была бы отброшена еще в форме, а если было бы позже, процедура не стала бы проверять время так тщательно, как проверяется для сделок на следующий рабочий день. 

Кстати, какой следующий рабочий день для заданных валют? Процедура возвращает 18 марта. Как в аптеке. Все верно. Беда.

Ладно, поехали дальше. Из таблицы параметров получаем окончание рабочего дня: 23:59, как и было сказано. Разница с Европой: минус час. Мы хотим добавить для страховки: плюс час, во дают дилеры! Итого ноль, принимай, Париж, наши сделки по ночам! Ладно, мне-то что, если Париж не возражает… Время сделки по Европе: 

17 марта 00:17. Все точно.

Теперь выясняется временная граница, после которой сделка не может быть принята как CLS. Делается это так: берется СЕЙЧАС, от него оттяпывается время, и вместо него к оставшейся дате приделывается параметр времени окончания рабочего дня. По идее, должно быть так: «17 марта» плюс «23:59»….

 
Стоп! Тут что-то не то. Процедура не использует здесь пришедший со спешащего компьютера параметр now (сейчас). Она берет значение «сейчас» из своей собственной функции.
ИЗ ФУНКЦИИ СЕРВЕРА.
Сколько времени у сервера?
Это мы знаем из даты запоминания. У сервера на часах 23 часа 51 минута. ШЕСТНАДЦАТОГО марта. 

Я закрыла глаза и потянулась. Потом открыла глаза и снова посмотрела на вызов функции сервера. Он был на месте, никуда не убежал.

Функция вернет 16 марта. Временная граница, сделки ПОЗЖЕ которой будут отброшены как « Cut of time is not OK » составит, таким образом, «16 марта 23:59».

А время сделки по Европе 17 марта 00:17. Вот так. Вот так.

ВОТ ТАК!!!!!
КОНТРАМОЦИЯ!!!!

:)))))))))))))))))))

Это у меня, значит, баг??…. А слабо вам, козлотуры, синхронизировать компьютеры ваших мудилеров в вашей пиздоватой системе?????

Стоп. А почему же исходная, пятая, сделка-то - прошла? ОНА-ТО – ПРОШЛА!!!!

Все то же самое. Переход через дату и функция сервера вместо параметра. Но сделка прошла. 
Я доверяю процедурам, которые сама писала. Что остается предполагать? Только то, что исходная сделка ВООБЩЕ не проходила эту проверку. А как это она могла ее не проходить?...

…Разве могла?…

...Минуту…
А зачем он вообще менял эту сделку? ЧТО он ТАКОГО изменил, этот мудилер, что при апдэйте снова принималось решение о CLS? Валюты те же. Сумма та же. Клиент тот же. 

….Б-же мой! Это не он, это я МУДИЛЕР.
ДАТА ВЫПОЛНЕНИЯ!!!!!….
Как же я сразу-то не посмотрела????!!!!!

Лезу – так и есть. Сделка исходно была на 19 МАРТА. Не на следующий рабочий день. Отсроченная. Время в этом случае просто никого не ебало. Процедура в последнюю вилку даже не зашла. Сделка прошла как CLS. 


После всех описанных кошмаров исправлялась проблема просто. Я убрала в процедуре вызов функции сервера и заменила его на приходящий параметр. Теперь была гарантия, что время вызова процедуры, равное СЕЙЧАС, и время окончания рабочего дня, -  будут относиться К ОДНОЙ И ТОЙ ЖЕ ДАТЕ. 


Проебалась я с этой процедурой часиков, между прочим, пять. Читать-то быстро… А исправление как таковое? Заняло, вместе с написанием трех строк отчета, ровно 2 минуты.

Программистам вообще платят ни за что. :)