How can I 'freeze' a dataset in a Datasnap server?
For a dataset which takes a very long time to open (it is a stored procedure), I would like to implement some kind of caching on the Datasnap server.
So if this dataset is loaded the first time and transferre开发者_StackOverflow社区d to the client (TClientDataSet), it should not be closed and reopened for the following requests unless the server restarts or a "reload" procedure on the server is called.
So after the first open, every new client would only receive a copy (clone) of the dataset without refreshing / reloading the server side dataset.
For a simple implementation of this dataset 'cache' the Datasnap server datamodule must not be created per session (because for each new session, the server side dataset would be closed until the client sends the request to open the DatasetProvider). Maybe I can find a solution to clone the dataset also for session datamodules but my basic question is:
Is there a way to override methods in the DatasetProvider so that the client can still open, but not close the server-side dataset?
Few years ago, some DataSnap server I worked on had to pull data from a very-very slow SQL Server 7 server. I then worked out a server cache "toy" based on TClientDataSets where "cached providers" are connected to those "server ClientDataSets" which in turns reads data from file cache or from database.
Cache was refreshed based on a set of specific hard-coded rules for each dataset. When the cache needs to be refreshed, server-ClientDataSet use a provider to pull data from database via ADOQuery and then the data is saved to the app-server disk using TClientDataSet's binary format. (it enables cache sharing between server instances).
To prevent different instances to pull information from database at the same time when it determines is time to update cache, very basic synchronization method was developed. A "control file" is created on disk during the data-retrieveral operation and deleted upon completion or failure. Before pull-data operation starts, the server instance checks for file existence. If it exists, enter a wait-loop until the file is not present and check for valid data in the .cds asociated file... and act according to that. If file don't exists, tries to create it, covering the very same millisecond case.
This was not a 24x7 application, just a kind of 12x6 :D. The method proved to be very good, I can't remember a single failure for this rude synchronization during almost 3 years I was maintaining that code.. but you maybe want to create a more robust mechanism.
When there's no need to refresh the cache, data is just loaded from disk.
All the cache work was done using the provider methods.
So, the relation was something like this:
//
// Client Server
//--------------- -----------------------------------------------------------------
// Cache refresh?
//
// Yes
// ----- Provider --- ADOQuery - DB
// ClientDataSet ---- Provider --- ClientDataSet --|
// ----- LoadFromFile
// No
//
//
Pseudo-code for need-to-update check and OpenDataSet was like this:
function CacheRequiresRefresh: Boolean
begin
if not IsPresentLocalData then
Result := True
else if ControlRecordIsMoreRecent then
Result := True
else if SomeOtherCondition then
Result := True
else
Result := False;
end;
function OpenDataSet;
begin
repeat
if CacheRequiresRefresh then
begin
if not ControlFilePresent then
if CreateControlFile then
begin
ConnectCDSToProvider;
CDS.Open;
end
else
if ControlFilePresent then
WaitUntilControlFileIsNotPresent
end
else
CDS.LoadFromFile('filename.cds');
until CDS.Active;
end;
I don't have access to the code anymore, sure I can't remember every detail, happily current servers are very good and fast enough not to need to think on this now... hope explained mechanism the way it worked. If you need clarification or further help, please commment.
精彩评论