Community Server on my mind

J-O Eriksson's blog


  • Running on CS 2.1 SP 2

    See top menu for subscription options

    Technology Blogs - Blog Top Sites

    BlogRankers.com

    Add to Technorati Favorites



Getting into Context with your CSJobs

While working on an add-on that forces users to change their passwords in CS, I stumbled upon a problem that I've seen others also have had problems with. To be able to get a context for certain operations/calls within the CS API. For example to get a UserSet with the help of a UserQuery requires a Context within the CS API.

I got help from  CarKnee over at CS.org on how to do that, and I thought it would be good to post it here as well for those of you that might do similar CSjobs. Now as CarKnee says there are a few CS Core jobs that already uses this code. But I believe it is important enough to lift it out as a good example.

So instead of doing the work directly in the Execute method. The IterateSiteSettings method is used and the work is done with a delegate method like this:

   1:  Public Sub Execute(ByVal node As System.Xml.XmlNode) 
   2:       Implements CommunityServer.Configuration.IJob.Execute
   3:   
   4:  SiteSettingsManager.IterateSiteSettings(New _
   5:       SiteSettingsListIterator(AddressOf RunMyJob))
   6:  End Sub
   7:   
   8:  Private Sub RunMyJob(ByVal SettingsID As Integer)
   9:   
  10:      CSContext.Create(SettingsID)
  11:   
  12:      'get the users here
  13:   
  14:  End Sub

In my case the work was to get a UserSet via a UserQuery, which I then could do within my RunMyJob method.

   1:  Dim objQuery As UserQuery = New CommunityServer.UserQuery()
   2:   
   3:  objQuery.Status = UserAccountStatus.Approved
   4:  objQuery.Order = SortOrder.Ascending
   5:  objQuery.IncludeHiddenUsers = False
   6:   
   7:  Dim objUserSet As UserSet = New UserSet()
   8:   
   9:  objUserSet = CommunityServer.Users.GetUsers(objQuery, False)
If you enjoyed this post Subscribe to my feed via RSS or e-mail!
Posted: Wednesday, October 18, 2006 8:03 AM by J-O Eriksson

Comments

Keyvan Nayyeri said:

The point you should know is the definition of CSJob is independent from CSContext except when comes into threading and here you come in Threading as an important concept. Take a look at my Spam Report job code: http://nayyeri.net/archive/2006/08/14/Community-Server-2.1-Spam-Report-Job.aspx There I defined all my logic in Execute() and of course, I used ThreadSets without any problem. I should see your older code to give more thoughts but if you're running your job on single thread, shouldn't get this problem because CSContext is available on same thread. So it *might* depend on your job configurations. Hope this makes sense :-)
# October 19, 2006 12:50 AM

J-O Eriksson said:

I have the job running on singleThread="false".

Question is, does a CSJob really run under a context, and if so which?

I don't know if ThreadSets differs from UserSets. Dave talked about he had looked in the souce code for UserSets, and saw it uses Contextes a lot.

# October 19, 2006 1:13 AM

Keyvan Nayyeri said:

Well,

Yes, I think all Sets use CSContext in the core but even if you wanted to use UserSets could apply the SettingsID value to create a CSContext on fly without using that delegate.

Yeap, I guess CSJob runs under a context.  You should distinguish between this context and the context you see in ASP.NET because it's not just limited to user request so it's not per request.  Some properties will be null if there isn't a request but not whole object.

I think it was better to do a debug in order to believe where that error occurs and take a look at trace to know what's going on.  You could at least define an error handling structure and save the error in Event Logs as the easist way to accomplish this.  Trace could help you to find where is the error.

# October 19, 2006 1:24 AM

J-O Eriksson said:

So how do you mean I could create a CSContext wihtout using this method. A CSContext with a valid SettingsID.

# October 19, 2006 2:11 AM

Keyvan Nayyeri said:

Simply :-D

All the SettingsID I've seen so far are 1000, just cheat it ;-)

# October 19, 2006 2:38 AM

J-O Eriksson said:

I knew it! ;-)

I rather don't cheat if I can help it. But do you see any problems using a delegate as above?

# October 19, 2006 2:43 AM

Keyvan Nayyeri said:

No problem in general but it's better to avoid using a delegate to jump from one thread to another when it's not necessary.

# October 19, 2006 7:06 AM

J-O Eriksson said:

And in this case, it's necessary, unless you want to "cheat" and hardcode the SettingsID. :-)

# October 19, 2006 7:20 AM

J-O Eriksson said:

If I am not mistaken, when using virtualization and running more than one community, there could be other SettingsID's. But of course then the discussion might end up in, for which Community is/should the job be run.

In any case, it seems like the method I describe in this article, is used in several of the built in jobs.

# October 19, 2006 7:24 AM

CarKnee said:

My take on the code I pointed you to is that the job will be run for all Site[Settings] you have defined in your CS Database. You could create the CSContext with a hard coded "1000", but what if you did have two sites that need this job? This way it will run fine for one site or multiple sites. Thanks for the credit ;) p.s. I really need to start a blog of my own. CarKnee
# October 19, 2006 7:51 AM

J-O Eriksson said:

Yes, that seems logical CarKnee.

Of course you need to start a blog, let me know when you do!

# October 19, 2006 8:21 AM

Keyvan Nayyeri said:

I don't know why you persist on making things complicated.

You don't want to cheat it?! Ok, don't do that but still you don't need to have a SettingsID to have a context.  If you take a look at CS architecture and APIs, can believe how can you create context.

And also I don't know why you jumbed into this approach before finding the reason for your error. You saw that I could use Sets in my job when they need a context in code so you had to be able to debug and use your old approach.  You had to do a good debug on your CSJob to find the reason.  The nice point in CSJob is it needs good experiences in order to do a good debug but still you can use alternative approaches to debug your jobs.

I want to finish this by saying: "Simpler code is better code" and you didn't attend to this and made your life harder.  The requirements for default CSJobs can be different from yours so you don't need to do whatever they did.  It can't be a reason to say if CS team used an approach, we should do it for every job we want to design.  Moving from one thread to another costs in .NET development and is sensitive especially when it runs every N minutes.

However, I just wanted to give my thoughts if they could help :-)

# October 19, 2006 10:34 AM

J-O Eriksson said:

Keyvan,

I think CarKnee, explains pretty good, one good reason to use my approach. In my opinion the code I've done is not complicated, also in my opinion, one should never ever hardcode values. But that's just my opinions.

# October 19, 2006 10:52 AM

CarKnee said:

J-O,

I finally got one (a blog) going. Not too much CS stuff there yet, but it is a start.

http://www.carknee.com

# January 5, 2007 10:28 AM

J-O Eriksson said:

Nice Carknee! :-)

I'll make sure to put a subscription in my RSS reader!

# January 7, 2007 3:45 AM

Sean Kearney's (CarKnee) Blog said:

"Rocket City Web" of the Community Server forums asked if it is possible to limit top posting members

# January 10, 2007 8:51 AM

J-O Eriksson said:

CarKnee,

I am not sure what you mean by that.

# January 11, 2007 4:13 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS