IBM®
Skip to main content
    Country/region select      Terms of use
 
 
   
     Home      Products      Services & solutions      Support & downloads      My account     

developerWorks  >  Lotus  >  Forums & community  >  Best Practice Makes Perfect

Best Practice Makes Perfect

A collaboration with Domino developers about how to do it and how to get it right in Domino

counting.gifAs I'm not seeing a good general overview of document sequential numbering for the Notes/Domino developer, I guess I'll have to write it myself. People have posted some interesting ideas in response to the last thread. Morten Clausen's caught my eye. He suggests to use a RunOnServer agent containing a CodeLock section that assigns the number. As he points out, this has the common failing of any system that provides true consecutive numbering, viz: there's a single point of failure -- and in addition, is rather a resource hog (the resource in question being agent threads on the "number server").

We could do something similar without the overhead of running an agent on the server, by taking advantage of a semaphore the server code already has in place. Specifically, it can detect whether a document you're saving has been saved by someone else since you loaded it into memory. So you might use a function such as this:

Function GetNextNumber(db As NotesDatabase, strUNID$, strItemName$) As Long
    ' db contains a doc where the "last used" number is stored.
    ' strUNID is the Universal ID of the document.

    ' strItemName is name of item in that doc containing last used #.
    Const MAXTRIES = 5
' if we get this many save conflicts something's wrong.
    Dim docCtr As NotesDocument

    Dim tries%

    Dim valCtr

   
tryAgain:

    Set docCtr = db.GetDocumentByUNID(strUNID)

    valCtr = docCtr.GetItemValue(strItemName)

    If Not Isnumeric(valctr(0)) Then ' first document is number 1

            GetNextNumber = 1

    Else

            GetNextNumber = 1& + Clng(valctr(0))

    End If

    docCtr.ReplaceItemValue strItemName, GetNextNumber

    If docCtr.Save(False, False, True) Then

            ' save worked!

            Exit Function

    Elseif tries < MAXTRIES Then

            ' save conflict -- try again

            tries = tries + 1

            Delete docCtr        ' clear it out of the cache.          
            Goto tryAgain

    Else

            Error 19891, "Retry count exceeded in GetNextNumber"

    End If

End Function

So you can have a single, non-replicated "number assignment" NSF used by various other applications when they need to get a unique number assigned. You can configure its operation within those various applications, with a profile document or however. For instance:

Function AssignSequentialNumber(dbThis As NotesDatabase, strProfile$, strItemName$) As Long
    ' get a local profile doc that configures the numbering mechanism

    ' strProfileName is the name of the profile doc.

    Dim docPro As NotesDocument

    Dim dbForNumbering As NotesDatabase

   
    Set docPro = dbThis.GetProfileDocument(strProfile)

   
    Dim strServer$        ' name of number server

    Dim strFilepath$ ' filepath of NSF containing numbering document.

    Dim strUNID$        ' UNID of document where counter is stored.

   
    strServer = docPro.GetItemValue("NumberingServer")(0)

    strFilepath = docPro.GetItemValue("NumberingFilepath")(0)

    strUNID = docPro.GetItemValue("NumberingUNID")(0)

    If strUNID = "" Or strFilepath = "" Or strServer = "" Then

            Error 19890, "Profile information missing in AssignSequentialNumber"

    End If

    Set dbForNumbering = New NotesDatabase(strServer, strFilepath)

    AssignSequentialNumber = GetNextNumber(dbForNumbering, strUNID, strItemName)

End Function

Some additional error checking would probably be beneficial, but that's the basic technique. And then of course you would format the returned number according to the requirements of your application.

By the way, I'm not recommending this approach unless you've determined that consecutive numbering is a really needed. As has been noted by others, often people ask for consecutive numbers when mere uniqueness would be sufficient.

Andre Guirard | 4 March 2008 02:23:00 AM ET | Taraccino Coffee, Minneapolis, MN, USA | Comments (5)


 Comments

1) Using save conflict checking to assign consecutive numbers
Nathan T. Freeman | 3/4/2008 7:17:46 AM

This degree of effort would be needed not just for consecutive numbers, but consecutive numbers with a constant increment.

I could have consecutive numbers easily. Just record the number of milliseconds since Jan 1, 1980 at save time. Those are consecutive and unique.

2) Using save conflict checking to assign consecutive numbers
Chris Hart | 3/5/2008 11:18:10 AM

I've used something very similar to this, checking the return value of Save. To allow working offline on a local replica, if the code can't reach the numbering server, the number is not set and an agent running on the server periodically checks for new unnumbered docs. That worked for me in testing and I have it in production, though I don't know how many people actually use a local replica.

I have one comment about the first block of code. I don't like using goto with a line label for that sort of retry. I think the code is cleaner with a loop, like "Do...Loop Until success Or tries = MAXTRIES", where success is a boolean set to True if the save succeeds.

3) Using save conflict checking to assign consecutive numbers
Thomas Bahn | 3/6/2008 4:02:17 PM

Simply GREAT idea, thank you for sharing.

Thomas

4) Using save conflict checking to assign consecutive numbers
Andre Guirard | 3/7/2008 4:06:53 PM

Mind you, like I said, the better way to deal with a request for sequential numbering is to argue against the requirement. This solution introduces a single point of failure for the system, and there are plenty of ways to get a good unique identifier that can be used offline and for applications that require high availability.

5) Using save conflict checking to assign consecutive numbers
Vlad | 3/21/2008 2:44:01 PM

I am using a RunOnServer agent with doc locking in a clustering environment but after 5 sec if the doc is still locked it exits and the user is warned that a # could not be assigned. The user will have to try later. It has been working fine but it is true that I do not have a lot of users for that application (under 10 users)

vlad

 Add a Comment
Subject:
   
Name:
Comment:  (No HTML - Links will be converted if prefixed http://)
 
Remember Me?     Cancel

Search this blog 

Disclaimer 

    About IBM Privacy Contact