Got more questions? Find advice on: ASP | SQL | XML | Regular Expressions
in Search
Welcome to WindowsAdvice Sign in | Join | Help

Christian Nordbakk

Some of this, and some of that...

Filter and Cache Latest Forum Posts

One thing you will notice if you use my example code for displaying the latest forum posts in a custom UserControl is that announcements and sticky posts are displayed too, and to make it worst, they are sorted by their sticky date (the date a post is set to un-stick) so that they always appear on top.

I haven’t found a really good solution to this problem, so if anyone knows one, please let me know. In the meantime I’ve come up with a routine that filters out all announcements and sticky posts, and goes like this:

int pageSize = 10;

ThreadSet threadSet = Threads.GetThreads(
  -1,
  0,
  pageSize,
  CSContext.Current.User,
  DateTime.MinValue,
  SortThreadsBy.LastPost,
  SortOrder.Descending,
  ThreadStatus.Open,
  ThreadUsersFilter.All,
  false,
  false,
  false,
  false
  );
       
ArrayList forRemoval = new ArrayList();
ArrayList forAddition = new ArrayList();
 
// Loop through the set and filter out announcements and sticky posts
foreach (object o in threadSet.Threads)
{
  Thread t = (Thread) o;
 
  if (t.IsAnnouncement || t.IsSticky)
  {
    forRemoval.Add(o);
 
    // We now need to fetch another thread to substitute
    // the one we just removed         
    while (true)
    {
      ThreadSet newThreads = Threads.GetThreads(
        -1,
        pageSize++,
        1,
        CSContext.Current.User,
        DateTime.MinValue,
        SortThreadsBy.LastPost,
        SortOrder.Descending,
        ThreadStatus.Open,
        ThreadUsersFilter.All,
        false,
        false,
        false,
        false
        );

      if (newThreads.Threads.Count > 0)
      {
        Thread newThread = (Thread) newThreads.Threads[0];
     
        // try again if it's a new announcement or sticky post
        if (!newThread.IsAnnouncement && !newThread.IsSticky)
        {
          forAddition.Add(newThread);
          break;
        }
      }
      else
      {
        break;
      }
    }
  }
}

// Remove unwanted posts
foreach (object o in forRemoval)
  threadSet.Threads.Remove(o);

// Add the substitute posts
threadSet.Threads.AddRange(forAddition);

As you can see this code is neither very aesthetically pleasing to look at, nor very efficient (as opposed to not having to do all this anyway). To counter the overhead created by this I’ve implemented caching of the filtered threads using the mechanisms provided by CommunityServer.

string cacheName = "LatestForumPosts-";
if (CSContext.Current.RolesCacheKey == null)
  cacheName += "Everyone";
else
  cacheName += CSContext.Current.RolesCacheKey;

ThreadSet threadSet;

if ((threadSet = (ThreadSet) CSCache.Get(cacheName)) == null)
{

  /***************************************
   Paste in the first code example here
  ****************************************/

  // Cache the filtered set
  CSCache.Insert(cacheName, threadSet, CSCache.MinuteFactor * 15);
}

This mostly counters the overhead brought on by the filter routine, by refreshing the list only once every 15 minutes for each user group. It works, but it just feels wrong, you now…

Sponsor
Published Tuesday, April 05, 2005 6:43 PM by cnordbakk
Filed under:

Comments

No Comments
Anonymous comments are disabled