Процедура используется нами уже пару лет для ежемесячной рассылки результатов расчета процентных ставок по дисконтным картам. Берет данные к рассылке из TSDiscountPost (наша времянка) и пытается автоматически адаптироваться к загрузке каналов связи (меняет размер пакета). Для формирования очереди в СМ2000 используются Супермажные функции :
Supermag.Smpostobject(null, 'DC', CardsToPostCurRow.Code, 0, null, 0, null) - Добавить дисконтную карту (DC, можно другой объект СМ ) к очереди рассылки и
Supermag.Smpostmakevp(counter) - создает виртуальный пакет.
Сразу оговорюсь - все константы заданы для НАШИХ условий рассылки пока не применялось архивирование пакетов перед отправкой.
----------------------------------------------------------------------------------
-- TimeOut - Макс время ожидания рассылки пакета в сек.
----------------------------------------------------------------------------------
procedure PostCards(TimeOutSec in number) is
Cursor TSCardsToPostCur is
Select t.Code
From Supermag.TSDiscountPost t
Order by t.code;
Type TSandedCards is table of VarChar2(50) not null
index by binary_integer;
SandedCards TSandedCards;
i binary_integer;
CardsToPostCurRow TSCardsToPostCur%RowType;
Counter number:= 0;
ElapsedTime number:= 0;
WaitSeconds number:= 480; --> 8мин
MaxCardsInPack number:= 1000;
AllPostCards number:= 0;
ObjectsCounter number:= 1;
VirtPackId number;
begin
Select Count(*) into AllPostCards
From Supermag.TSDiscountPost;
If AllPostCards < MaxCardsInPack Then
MaxCardsInPack:= AllPostCards;
end if;
Open TSCardsToPostCur;
loop
fetch TSCardsToPostCur into CardsToPostCurRow;
exit when TSCardsToPostCur%notfound;
Supermag.Smpostobject(null, 'DC', CardsToPostCurRow.Code, 0, null, 0, null);
SandedCards(counter):= CardsToPostCurRow.Code;
counter:= counter+1;
If counter = MaxCardsInPack Then
-- commit;
Supermag.Smpostmakevp(counter);
Select max(q.virtpack) into VirtPackId
From supermag.smpostqueue q
Where q.objId = CardsToPostCurRow.Code and
q.objtype = 'DC' and
q.target is null;
counter:= 0;
loop -- Рассылка
DBMS_LOCK.SLEEP (WaitSeconds);
ElapsedTime:= ElapsedTime+ WaitSeconds;
WaitSeconds:= 30;
Select count(*) into ObjectsCounter
From supermag.smpostqueue q
Where q.virtpack = VirtPackId;
exit when ObjectsCounter = 0;
If ElapsedTime > TimeOutSec Then
RAISE_APPLICATION_ERROR(-20001, 'Превышено допустимое время ожидания рассылки пакета', True);
end if;
end loop;
for i in 0 .. SandedCards.count -1
loop
Delete
From Supermag.TSDiscountPost p
Where p.code = SandedCards(i);
end loop;
commit;
SandedCards.Delete;
If ElapsedTime <= 720 Then -->12min
If MaxCardsInPack < 3000 Then
MaxCardsInPack:= MaxCardsInPack + 250;
else
MaxCardsInPack:= 3000;
end if;
else
If MaxCardsInPack > 1500 Then
MaxCardsInPack:= MaxCardsInPack - 500;
else
MaxCardsInPack:= 1000;
end if;
end if;
Select Count(*) into AllPostCards
From Supermag.TSDiscountPost;
If AllPostCards < MaxCardsInPack Then
MaxCardsInPack:= AllPostCards;
end if;
ElapsedTime:= 0;
WaitSeconds:= 480; --> 8мин
ObjectsCounter:= 1;
end if;
end loop;
Close TSCardsToPostCur;
exception
When Others Then
rollback;
If TSCardsToPostCur%IsOpen Then
Close TSCardsToPostCur;
end if;
RAISE_APPLICATION_ERROR (-20000, 'Процедура PostCards', True);
end PostCards;