BEGIN PRINT @result RAISERROR ( 'Lock failed to acquire for Proj Aggregate table population.', 16, 1 ) END ELSE BEGIN --mutex acquired --cache ageing...we allow 1 min DECLARE @CacheAge DATETIME = DATEADD(mi,-1,GETDATE()) --take this opportunity to purge the DUMMY table of anything older than 1 min DELETE FROM dbo.ProjectCache WHERE CacheInsertDateTime < @CacheAge
IF EXISTS ( SELECT input.ProjectID ,pam.ProjectID FROM #ProjectIDList input LEFT JOIN dbo.ProjectCache pam ON input.ProjectID = pam.ProjectID --natural key AND pam.CacheInsertDateTime > @CacheAge --cache has to be within age WHERE pam.ProjectID IS NULL --if we are missing cache rows for the ProjectID, fail it. ) BEGIN --cache is stale or Project requested does not live in cache BEGIN INSERT INTO dbo.ProjectCache SELECT input.ProjectID ... FROM ... END END
--get the data SELECT * FROM dbo.ProjectCache EXEC @result = sp_releaseapplock @Resource = 'Proj Aggregate table population' END --mutex acquired COMMIT END
Here we check to see that we obtained a lock. In no case should this ever fail, it will simply wait to obtain the mutex, which is an exclusive lock on the data cache table.
Now that I have my mutex I want to see if the data cache is stale and if so purge it.
Since each report has a set of params we need to make sure our cache has those params (ProjectID).
Here we rebuild the cache.
And finally we return the data from the cache as requested, release the app lock, and commit the transaction.
Assume now that a split second after the first user enters the procedure a second user makes the same request. And then a third user makes the same request a second after that. Here is the order of events.
User One
User Two
User Three
Procedure is called
Mutex is granted
Since no data is in the cache or it is stale we begin to populate the cache.
Procedure is called
Mutex is not granted. User is blocked.
Procedure is called
Mutex is not granted. User is blocked.
Waiting on Procedure to build data cache...
Waiting on Procedure to build data cache...
Waiting on Procedure to build data cache...
Procedure finally completes. Data cache is rebuilt. Data is returned to the client and mutex is released.
Mutex is granted.
Data cache is not stale, all ProjectIDs are available
Data is returned immediately to the client
Mutex is released.
Mutex is granted.
Data cache is not stale, all ProjectIDs are available