Hi guys
in RPackage there is a method named withOrganizer:do: defined as follows and I would like to test it to understand really if it does what it says. withOrganizer: aNewOrganizer do: aBlock "Perform an action locally to aNewOrganizer. Does not impact any other organizers." | old shouldRegisterAtTheEnd| [ old := self organizer. shouldRegisterAtTheEnd := false. old hasRegistered ifTrue: [ old unregister. shouldRegisterAtTheEnd := true. ]. self organizer: aNewOrganizer. aBlock cull: aNewOrganizer.] ensure: [ self organizer: old. shouldRegisterAtTheEnd ifTrue: [ self organizer register. ]. aNewOrganizer unregister. ] So I wrote two tests testWithDoIsCorrectlyReinstallingDefault "self debug: #testWithDoIsCorrectlyReinstallingDefault" | current empty | current := RPackageOrganizer default. empty := RPackageOrganizer basicNew initialize. RPackage withOrganizer: empty do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty). self deny: (SystemAnnouncer announcer hasSubscriber: current)]. self assert: (SystemAnnouncer announcer hasSubscriber: current). self deny: (SystemAnnouncer announcer hasSubscriber: empty) and testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt" | current empty | current := RPackageOrganizer default. empty := RPackageOrganizer basicNew initialize. RPackage withOrganizer: empty do: [ self error. self assert: (SystemAnnouncer announcer hasSubscriber: empty). self deny: (SystemAnnouncer announcer hasSubscriber: current)]. self assert: (SystemAnnouncer announcer hasSubscriber: current). self deny: (SystemAnnouncer announcer hasSubscriber: empty) Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument is executed. Does anybody have an idea how I can do that. because self error does not work. Stef |
First question what i wanna ask is:
- why do you need to play with two different instances of organizer, and especially in such manner (temporary swapping forth and back)? This code doesn't looks to be good. On 24 April 2011 00:44, Stéphane Ducasse <[hidden email]> wrote: > Hi guys > > in RPackage there is a method named withOrganizer:do: defined as follows and I would like to test it to understand really if it does > what it says. > > withOrganizer: aNewOrganizer do: aBlock > "Perform an action locally to aNewOrganizer. Does not impact any other organizers." > > | old shouldRegisterAtTheEnd| > [ > old := self organizer. > shouldRegisterAtTheEnd := false. > old hasRegistered ifTrue: [ > old unregister. > shouldRegisterAtTheEnd := true. > ]. > self organizer: aNewOrganizer. > aBlock cull: aNewOrganizer.] ensure: [ > self organizer: old. > shouldRegisterAtTheEnd ifTrue: [ > self organizer register. > ]. > aNewOrganizer unregister. > ] > > > So I wrote two tests > > testWithDoIsCorrectlyReinstallingDefault > "self debug: #testWithDoIsCorrectlyReinstallingDefault" > > | current empty | > current := RPackageOrganizer default. > empty := RPackageOrganizer basicNew initialize. > RPackage withOrganizer: empty > do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty). > self deny: (SystemAnnouncer announcer hasSubscriber: current)]. > self assert: (SystemAnnouncer announcer hasSubscriber: current). > self deny: (SystemAnnouncer announcer hasSubscriber: empty) > > > and > > > testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt > "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt" > > | current empty | > current := RPackageOrganizer default. > empty := RPackageOrganizer basicNew initialize. > RPackage withOrganizer: empty > do: [ self error. > self assert: (SystemAnnouncer announcer hasSubscriber: empty). > self deny: (SystemAnnouncer announcer hasSubscriber: current)]. > self assert: (SystemAnnouncer announcer hasSubscriber: current). > self deny: (SystemAnnouncer announcer hasSubscriber: empty) > > Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument > is executed. Does anybody have an idea how I can do that. because self error does not work. > > Stef > > > > > -- Best regards, Igor Stasenko AKA sig. |
> First question what i wanna ask is:
> - why do you need to play with two different instances of organizer, > and especially in such manner (temporary swapping forth and back)? > > This code doesn't looks to be good. Igor can you reply to my question instead of questioning because it just slows me down. Now the answer: when we run the tests we do not run them in the default organizer because if something wrong happens then this is simply harakiri. So all the tests are performed in a separated created on the fly organizer. And I think that this is good to do it like that else I have to have a global variable and the rest. This design is the result of changes doru pushed me to do and they are good. Now this good is bad and not written my me and I'm trying to clean it and this is why I need to write tests because I want the Package code to be bullet proof. Stef > > > On 24 April 2011 00:44, Stéphane Ducasse <[hidden email]> wrote: >> Hi guys >> >> in RPackage there is a method named withOrganizer:do: defined as follows and I would like to test it to understand really if it does >> what it says. >> >> withOrganizer: aNewOrganizer do: aBlock >> "Perform an action locally to aNewOrganizer. Does not impact any other organizers." >> >> | old shouldRegisterAtTheEnd| >> [ >> old := self organizer. >> shouldRegisterAtTheEnd := false. >> old hasRegistered ifTrue: [ >> old unregister. >> shouldRegisterAtTheEnd := true. >> ]. >> self organizer: aNewOrganizer. >> aBlock cull: aNewOrganizer.] ensure: [ >> self organizer: old. >> shouldRegisterAtTheEnd ifTrue: [ >> self organizer register. >> ]. >> aNewOrganizer unregister. >> ] >> >> >> So I wrote two tests >> >> testWithDoIsCorrectlyReinstallingDefault >> "self debug: #testWithDoIsCorrectlyReinstallingDefault" >> >> | current empty | >> current := RPackageOrganizer default. >> empty := RPackageOrganizer basicNew initialize. >> RPackage withOrganizer: empty >> do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty). >> self deny: (SystemAnnouncer announcer hasSubscriber: current)]. >> self assert: (SystemAnnouncer announcer hasSubscriber: current). >> self deny: (SystemAnnouncer announcer hasSubscriber: empty) >> >> >> and >> >> >> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt >> "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt" >> >> | current empty | >> current := RPackageOrganizer default. >> empty := RPackageOrganizer basicNew initialize. >> RPackage withOrganizer: empty >> do: [ self error. >> self assert: (SystemAnnouncer announcer hasSubscriber: empty). >> self deny: (SystemAnnouncer announcer hasSubscriber: current)]. >> self assert: (SystemAnnouncer announcer hasSubscriber: current). >> self deny: (SystemAnnouncer announcer hasSubscriber: empty) >> >> Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument >> is executed. Does anybody have an idea how I can do that. because self error does not work. >> >> Stef >> >> >> >> >> > > > > -- > Best regards, > Igor Stasenko AKA sig. > |
On 24 April 2011 11:59, Stéphane Ducasse <[hidden email]> wrote:
>> First question what i wanna ask is: >> - why do you need to play with two different instances of organizer, >> and especially in such manner (temporary swapping forth and back)? >> >> This code doesn't looks to be good. > > Igor can you reply to my question instead of questioning because it just slows me down. > > Now the answer: > when we run the tests we do not run them in the default organizer because if something wrong happens > then this is simply harakiri. > So all the tests are performed in a separated created on the fly organizer. > And I think that this is good to do it like that else I have to have a global variable and the rest. > This design is the result of changes doru pushed me to do and they are good. > Now this good is bad and not written my me and I'm trying to clean it and this is why I need to > write tests because I want the Package code to be bullet proof. > i am puzzled. You wanna to be sure that ensure block are executed? It is. However if error was triggered during ensure block evaluation, it may not complete everything you put there. And for test you can use non-local return to trigger ensure block: testWithDoIsCorrectlyReinstallingDefault "self debug: #testWithDoIsCorrectlyReinstallingDefault" | current empty | current := RPackageOrganizer default. empty := RPackageOrganizer basicNew initialize. self doWith:current and:empty. self assert: (SystemAnnouncer announcer hasSubscriber: current). self deny: (SystemAnnouncer announcer hasSubscriber: empty) doWith:current and:empty RPackage withOrganizer: empty do: [ ^ self ]. Or with error: testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt" | current empty | current := RPackageOrganizer default. empty := RPackageOrganizer basicNew initialize. [ RPackage withOrganizer: empty do: [ self error ]. ] on: Error do: [:ex | ]. self assert: (SystemAnnouncer announcer hasSubscriber: current). self deny: (SystemAnnouncer announcer hasSubscriber: empty) > Stef >> >> >> On 24 April 2011 00:44, Stéphane Ducasse <[hidden email]> wrote: >>> Hi guys >>> >>> in RPackage there is a method named withOrganizer:do: defined as follows and I would like to test it to understand really if it does >>> what it says. >>> >>> withOrganizer: aNewOrganizer do: aBlock >>> "Perform an action locally to aNewOrganizer. Does not impact any other organizers." >>> >>> | old shouldRegisterAtTheEnd| >>> [ >>> old := self organizer. >>> shouldRegisterAtTheEnd := false. >>> old hasRegistered ifTrue: [ >>> old unregister. >>> shouldRegisterAtTheEnd := true. >>> ]. >>> self organizer: aNewOrganizer. >>> aBlock cull: aNewOrganizer.] ensure: [ >>> self organizer: old. >>> shouldRegisterAtTheEnd ifTrue: [ >>> self organizer register. >>> ]. >>> aNewOrganizer unregister. >>> ] >>> >>> >>> So I wrote two tests >>> >>> testWithDoIsCorrectlyReinstallingDefault >>> "self debug: #testWithDoIsCorrectlyReinstallingDefault" >>> >>> | current empty | >>> current := RPackageOrganizer default. >>> empty := RPackageOrganizer basicNew initialize. >>> RPackage withOrganizer: empty >>> do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty). >>> self deny: (SystemAnnouncer announcer hasSubscriber: current)]. >>> self assert: (SystemAnnouncer announcer hasSubscriber: current). >>> self deny: (SystemAnnouncer announcer hasSubscriber: empty) >>> >>> >>> and >>> >>> >>> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt >>> "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt" >>> >>> | current empty | >>> current := RPackageOrganizer default. >>> empty := RPackageOrganizer basicNew initialize. >>> RPackage withOrganizer: empty >>> do: [ self error. >>> self assert: (SystemAnnouncer announcer hasSubscriber: empty). >>> self deny: (SystemAnnouncer announcer hasSubscriber: current)]. >>> self assert: (SystemAnnouncer announcer hasSubscriber: current). >>> self deny: (SystemAnnouncer announcer hasSubscriber: empty) >>> >>> Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument >>> is executed. Does anybody have an idea how I can do that. because self error does not work. >>> >>> Stef >>> >>> >>> >>> >>> >> >> >> >> -- >> Best regards, >> Igor Stasenko AKA sig. >> > > > -- Best regards, Igor Stasenko AKA sig. |
>>>
> i am puzzled. You wanna to be sure that ensure block are executed? > It is. I want to write a test that shows and tests the withOrganizer:do: semantics. In particular that the ensure is executed and that the context set by the withOrganizer: is only present in the do: block. > However if error was triggered during ensure block evaluation, it may > not complete everything you put there. Sure this is normal. > And for test you can use non-local return to trigger ensure block: > > | current empty | > current := RPackageOrganizer default. > empty := RPackageOrganizer basicNew initialize. > > [ > RPackage withOrganizer: empty > do: [ self error ]. > ] on: Error do: [:ex | ]. > > self assert: (SystemAnnouncer announcer hasSubscriber: current). > self deny: (SystemAnnouncer announcer hasSubscriber: empty) Yes this is what I was thinking to do. because a self error alone was not. Stef |
In reply to this post by Igor Stasenko
>
> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt > "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt" > > | current empty | > current := RPackageOrganizer default. > empty := RPackageOrganizer basicNew initialize. > > [ > RPackage withOrganizer: empty > do: [ self error ]. > ] on: Error do: [:ex | ]. > > self assert: (SystemAnnouncer announcer hasSubscriber: current). > self deny: (SystemAnnouncer announcer hasSubscriber: empty) Igor but how can I specify that I want an error to occur in the do: and that I do not want to trap it but that the ensure should trap it. Is the ensure execute if I trap the error like that? Stef |
In reply to this post by Igor Stasenko
here is a simpler case
do: aBlock x := 5. [aBlock value] ensure: [x :=3] testDo "self run: #testDo" self do: [ self error]. self assert: x = 3 and I do not understand why ensure is not executed :( because I always want the ensure to happen not only on ifCurtailed: Stef |
On 24 April 2011 13:26, Stéphane Ducasse <[hidden email]> wrote:
> here is a simpler case > > do: aBlock > > x := 5. > [aBlock value] ensure: [x :=3] > > testDo > "self run: #testDo" > > self do: [ self error]. > self assert: x = 3 > > > and I do not understand why ensure is not executed :( > because I always want the ensure to happen not only on ifCurtailed: > error are not causing ensure block to trigger. only after you either abandon or proceed, an ensure block will be executed. > Stef > -- Best regards, Igor Stasenko AKA sig. |
On Apr 24, 2011, at 12:43 PM, Igor Stasenko wrote: > On 24 April 2011 13:26, Stéphane Ducasse <[hidden email]> wrote: >> here is a simpler case >> >> do: aBlock >> >> x := 5. >> [aBlock value] ensure: [x :=3] >> >> testDo >> "self run: #testDo" >> >> self do: [ self error]. >> self assert: x = 3 >> >> >> and I do not understand why ensure is not executed :( >> because I always want the ensure to happen not only on ifCurtailed: >> > > error are not causing ensure block to trigger. so what is causing them to trigger. I always thought ensure: was really giving that warranty. So this is really scary to me. I wrote that and this is green. testDo2 "self run: #testDo2 1 run, 1 passes, 0 expected failures, 0 failures, 0 errors, 0 unexpected passes" [self do: [ self error] ] on: Error do: [:ex | ]. self assert: x = 3. To me it means that I should not use ensure because it makes no sense to wrap the withOrganizer in a on: do: block outside. So I do not see the real use of ensure: Shit..... Stef > only after you either abandon or proceed, an ensure block will be executed. > > >> Stef >> > > -- > Best regards, > Igor Stasenko AKA sig. > |
In reply to this post by Igor Stasenko
I read what I wrote on the exception chapter and also the comments of the ensure: method
and I do not get why >> > error are not causing ensure block to trigger. > only after you either abandon or proceed, an ensure block will be executed. to me it completely defeats the purpose of ensure: or ifCurtailed: Evaluate a termination block after evaluating the receiver, regardless of whether the receiver's evaluation completes. So when should ensure: be used? if I get an error because of a file problem will it be triggered? I do not see how this is working in that case Stef PastedGraphic-1.pdf (86K) Download Attachment |
In reply to this post by Igor Stasenko
How can I ensure that really in case of error or not a piece of code is executed.
Now I'm totally confused by the semantics of ensure: So I wrote that: testOnDo "self run: #testOnDo " self doOnDo: [ self error]. self assert: x = 3. x := 77. self doOnDo: [x = 21]. self assert: x = 3 ensure x := 3 doOnDo: aBlock x := 5. [aBlock value. self ensure] on: Error do: [:ex | self ensure]. |
In reply to this post by Igor Stasenko
Ok I got it I ws confused by SUnit interference
testDo "self run: #testDo" self do: [ Error signal]. self assert: x = 3 self run: #testDo -> red tests self debug: #testDo + proceed -> green tests |
On 24 April 2011 15:13, Stéphane Ducasse <[hidden email]> wrote:
> Ok I got it I ws confused by SUnit interference > :)) > testDo > "self run: #testDo" > > self do: [ Error signal]. > self assert: x = 3 > > > > self run: #testDo -> red tests > > self debug: #testDo + proceed -> green tests > Yes, sunit interrupts execution at the moment when error was triggered, before unwinding the stack. -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Stéphane Ducasse
On 24.04.2011 14:13, Stéphane Ducasse wrote:
> Ok I got it I ws confused by SUnit interference > > testDo > "self run: #testDo" > > self do: [ Error signal]. > self assert: x = 3 > > > > self run: #testDo -> red tests > > self debug: #testDo + proceed -> green tests The ensure runs, but at that point the test already failed, see it says "1 errors", not "1 failures" :) To see it manually, you could put Transcript show: 'Foo' or some such in the ensure block instead, and notice how the Transcript is written :) Cheers, Henry ps. It's easier to just write aBlock ensure: [blabla] instead of [aBlock value] ensure: [blabla] ... if aBlock REALLY is a block, and not aValuable, of course := |
In reply to this post by Stéphane Ducasse
On 24.04.2011 12:05, Stéphane Ducasse wrote:
>> i am puzzled. You wanna to be sure that ensure block are executed? >> It is. > I want to write a test that shows and tests the withOrganizer:do: semantics. > In particular that the ensure is executed and that the context set by the withOrganizer: is only present > in the do: block. > In other words, another use case probably written more cleanly using the non-existing Announcer >> #suspend: subscriber while: aBlock ;) Cheers, Henry |
good suggestion.
I will check that. Stef On Apr 26, 2011, at 3:11 PM, Henrik Sperre Johansen wrote: > On 24.04.2011 12:05, Stéphane Ducasse wrote: >>> i am puzzled. You wanna to be sure that ensure block are executed? >>> It is. >> I want to write a test that shows and tests the withOrganizer:do: semantics. >> In particular that the ensure is executed and that the context set by the withOrganizer: is only present >> in the do: block. >> > In other words, another use case probably written more cleanly using the non-existing > Announcer >> #suspend: subscriber while: aBlock > > ;) > > Cheers, > Henry > |
In reply to this post by Henrik Sperre Johansen
On 26 April 2011 15:11, Henrik Sperre Johansen
<[hidden email]> wrote: > On 24.04.2011 12:05, Stéphane Ducasse wrote: >>> >>> i am puzzled. You wanna to be sure that ensure block are executed? >>> It is. >> >> I want to write a test that shows and tests the withOrganizer:do: >> semantics. >> In particular that the ensure is executed and that the context set by the >> withOrganizer: is only present >> in the do: block. >> > In other words, another use case probably written more cleanly using the > non-existing > Announcer >> #suspend: subscriber while: aBlock > What is potential implementation? Announcer >>suspend: subscriber while: aBlock | subscriptions | subscriptions := OrderedCollection new. registry subscriptionsOf: subscriber do: [:each | subscriptions add: each ]. registry removeSubscriber: subscriber. ^ aBlock ensure: [ subscriptions do: [:ea | registry add: ea ] ] The problem is that its not doing exactly what is said: - it suspends existing subscriptions instead of suspending subscriber. The difference between those are subtle but important: a suspended subscriber should not receive any announcements during block evaluation, even if it may want to subscribe to new ones during given block evaluation. And the code above not handling this case , as well as it doesn't handling the case when subscriber may want to occasionally unsubscribe from some announcements during block evaluation. So, for doing this correctly, a subscription registry should keep a list of suspended subscribers somewhere, and then in #deliver: it should check if subscription's subscriber are not in that list, and only then let it deliver an announcement. The problem is that delivery time will slowdown considerably, because for every subscription you should check if it's subscriber are not in 'suspended subscribers' list. So, it is really depends on intent. Suspending a concrete subscription will require adding 'suspended' flag to subscription state. But suspending a concrete subscriber and to guarantee that it won't receive any announcements (even if it will subscribe for a new ones during suspension time), can't be solved by having 'suspended' ivar on subscription. You have to manage suspended subscribers list separately. -- Best regards, Igor Stasenko AKA sig. |
On 26.04.2011 17:37, Igor Stasenko wrote:
> On 26 April 2011 15:11, Henrik Sperre Johansen > <[hidden email]> wrote: >> On 24.04.2011 12:05, Stéphane Ducasse wrote: >>>> i am puzzled. You wanna to be sure that ensure block are executed? >>>> It is. >>> I want to write a test that shows and tests the withOrganizer:do: >>> semantics. >>> In particular that the ensure is executed and that the context set by the >>> withOrganizer: is only present >>> in the do: block. >>> >> In other words, another use case probably written more cleanly using the >> non-existing >> Announcer>> #suspend: subscriber while: aBlock >> > What is potential implementation? > > Announcer>>suspend: subscriber while: aBlock > | subscriptions | > > subscriptions := OrderedCollection new. > > registry subscriptionsOf: subscriber do: [:each | > subscriptions add: each > ]. > registry removeSubscriber: subscriber. > > ^ aBlock ensure: [ subscriptions do: [:ea | registry add: ea ] ] > > > The problem is that its not doing exactly what is said: > - it suspends existing subscriptions instead of suspending subscriber. > > The difference between those are subtle but important: > a suspended subscriber should not receive any announcements during > block evaluation, > even if it may want to subscribe to new ones during given block evaluation. > And the code above not handling this case , as well as it doesn't > handling the case when subscriber may want > to occasionally unsubscribe from some announcements during block evaluation. > > So, for doing this correctly, a subscription registry should keep a > list of suspended subscribers somewhere, > and then in #deliver: > it should check if subscription's subscriber are not in that list, and > only then let it deliver an announcement. > > The problem is that delivery time will slowdown considerably, because > for every subscription you should check > if it's subscriber are not in 'suspended subscribers' list. > > > So, it is really depends on intent. Suspending a concrete subscription > will require adding 'suspended' flag to subscription state. > But suspending a concrete subscriber and to guarantee that it won't > receive any announcements (even if it will subscribe for > a new ones during suspension time), can't be solved by having > 'suspended' ivar on subscription. You have to manage suspended > subscribers list separately. > comment is NOT supported at the moment, nothing more imho :) Simply providing something like: suspend(SubscriptionsOf): subscriber while: aBlock |oldSubs| oldSubs := subscriptionRegistry removeSubscriber: subscriber. aBlock ensure: [oldSubs do: [ :each | subscriptionRegistry add: each]] is better than nothing. Cheers, Henry |
In reply to this post by Igor Stasenko
I see. Subtle. May be a solution not slowing everything but more limited is the way to go.
>>>> >>>> i am puzzled. You wanna to be sure that ensure block are executed? >>>> It is. >>> >>> I want to write a test that shows and tests the withOrganizer:do: >>> semantics. >>> In particular that the ensure is executed and that the context set by the >>> withOrganizer: is only present >>> in the do: block. >>> >> In other words, another use case probably written more cleanly using the >> non-existing >> Announcer >> #suspend: subscriber while: aBlock >> > > What is potential implementation? > > Announcer >>suspend: subscriber while: aBlock > | subscriptions | > > subscriptions := OrderedCollection new. > > registry subscriptionsOf: subscriber do: [:each | > subscriptions add: each > ]. > registry removeSubscriber: subscriber. > > ^ aBlock ensure: [ subscriptions do: [:ea | registry add: ea ] ] > > > The problem is that its not doing exactly what is said: > - it suspends existing subscriptions instead of suspending subscriber. > > The difference between those are subtle but important: > a suspended subscriber should not receive any announcements during > block evaluation, > even if it may want to subscribe to new ones during given block evaluation. > And the code above not handling this case , as well as it doesn't > handling the case when subscriber may want > to occasionally unsubscribe from some announcements during block evaluation. > > So, for doing this correctly, a subscription registry should keep a > list of suspended subscribers somewhere, > and then in #deliver: > it should check if subscription's subscriber are not in that list, and > only then let it deliver an announcement. > > The problem is that delivery time will slowdown considerably, because > for every subscription you should check > if it's subscriber are not in 'suspended subscribers' list. > > > So, it is really depends on intent. Suspending a concrete subscription > will require adding 'suspended' flag to subscription state. > But suspending a concrete subscriber and to guarantee that it won't > receive any announcements (even if it will subscribe for > a new ones during suspension time), can't be solved by having > 'suspended' ivar on subscription. You have to manage suspended > subscribers list separately. > > -- > Best regards, > Igor Stasenko AKA sig. > |
Free forum by Nabble | Edit this page |