Briefcase as a service

Hi

I have Briefcase app with async Save to Server procedure which using Clone MemTable ( as discussed here ) , but yet still not stable when WiFi connection is slow. Windows app can run for a while and suddenly show error messages = invalid pointer and hang up at some moment.

My assumption that if threaded process takes long time it should be stopped and transaction rolled back.
One of the questions I have : would be stop working thread “transaction safe”? Can I assume that any transaction should be finished in 1-3 seconds and if not finished stopped? How this scenario will be RO friendly?

Next to what I was discussing above is: can I run Briefcase as a service on Client computer?
The idea is to run main app only in Briefcase mode to save data and all “Data Saving to Server” procedures have organised as service, which will run apply updates/refresh once in a 5 minutes or so.

In this case can I have two ((Delphi)app and (.NET)service) processes connected to same briefcase file and can service recognise delta and apply without interfering to main app?

I think that maybe in this scenario Briefcase should have a locking mechanism ( or something to avoid a mess with shared access?)

Any help will be much appreciated.

you can manually handle transactions. see OnUpdateDataBeginTransaction, OnUpdateDataCommitTransaction and OnUpdateDataRollBackTransaction events of DAService

it is possible

Thank you, Evgeny.
Can I check if connection is alive before Transaction?
May be with
property Connection: IDAConnection read write
or any other way?

Would you give me an simple example of how to use events of DAService.
Sorry could not find in examples of RO Delphi projects.

calling Connection will return existed connection or create a new one.

imagine scenario:

  • client calls custom server method
  • OnUpdateDataBeginTransaction, OnUpdateDataCommitTransaction and OnUpdateDataRollBackTransaction events should set aUseDefaultTransactionLogic to False
  • in this custom method, you call Connection.StartTransaction manually
  • get current timestamp
  • execute long SQL operation
  • compare timestamp with current time
  • call Connection.Commit or Connection.Rollback depended on previous comparing

Hi Evgeny
Can I check if connection is alive before Transaction?
In the moment I’m using “ping” function to detect if app can connect to network is it better way to do so with RO?
As well will be cool to get info about is it Relativity Server running and accessible?

Hi,
connection has property Connected - you can use it.
you can call any empty server method - if some problems will be detected, it will fail.
for local service - you can check for Relativity.exe process in memory, for remove service - just connect to relativity

Sorry could not find those methods in Delphi RemObjects,
My assumption that
RemoteDataAdapter.RemoteService.CheckCanConnect(true)
can be used , but I’m not sure what type of data this method will return and how I can adopt it for my app.
say fro instance RemoteDataAdapter.RemoteService.CheckCanConnect(true)
may be can return string “Service name” , but getting this error:

[dcc32 Error] StockDM.pas(305): E2010 Incompatible types: ‘string’ and ‘procedure, untyped pointer or untyped parameter’

My assumption that this is procedure and does not return parameter

One problem I can see , that if connection is lost and we using function like RemoteDataAdapter.RemoteService.Login
takes up to 22 seconds to return an error : “Socket Error 10060 Connection timeout” , which is enormous comparing to simple “ping”

we mess connection term: I mean connection to DB server on server side, but you - connection to server app from client-side.
You can switch to super channels - they have Connected property and you can see when connection is dropped

Hi I can see it now ROIndySuperHTTPChannel1 has connected property.

Now I’m trying something like this to see if app can connect:
I have Relativity server NEtwork settings changed to SuperHttp server channel type
and in app trying :

procedure TClientForm.Button1Click(Sender: TObject);
begin

 if  ClientDataModule.ROIndySuperHTTPChannel1.Connected then showmessage('connected 1') else  showmessage('not 1');
 if  ClientDataModule.ROSynapseSuperHTTPChannel1.Connected  then  showmessage('connected 2') else  showmessage('not 2');
end;
  1. Have Relativity server up and running and
    ROIndySuperHTTPChannel1 returning ‘connected 1’
    ROSynapseSuperHTTPChannel1 returning ‘not 2’

  2. Have Relativity server stopped and
    ROIndySuperHTTPChannel1 returning ‘connected 1’
    ROSynapseSuperHTTPChannel1 returning ‘not 2’

  3. Have Relativity server shutdown and
    ROIndySuperHTTPChannel1 returning ‘connected 1’
    ROSynapseSuperHTTPChannel1 returning ‘not 2’

if I’m have app restarted ROIndySuperHTTPChannel1 is showing right result .
Do I have to “refresh” somehow ROIndySuperHTTPChannel1 before calling .Connected ?

SuperHTTP channel has 120 sec timeout for waiting thread so it can recognize that server was closed during this time.
try to test SuperTCP channel, it has lower timeout

Thank you have it sorted.
Is it a matter that supertcp://localhost:8095 has default port : 8095? can I use 7100 or 7099 … instead or this will interfere with something else?

you can specify any port.

Thank you!
Sorry , the last one : Does RemoteDataAdapter.RemoteService.CheckCanConnect(true) returning any data or this is procedure that suppose to change some “CanConnect” property on the server ?

this method only checks that RemoteService is configured correctly, i.e. has channel, message and ServiceName.

Does it returning anything like true/false so I can utilise it somehow?

procedure TRORemoteService.CheckCanConnect(CheckServiceName : boolean = TRUE);
begin
  Check(Channel=NIL, Name + '.'+err_ChannelMustBeAssigned);
  Channel.CheckProperties;
  Check(Message=NIL, Name + '.'+err_MessageMustBeAssigned);
  Message.CheckProperties;
  if CheckServiceName then Check(ServiceName='', Name + '.'+err_ServiceNameMustBeSpecified);
end;

Cheers!

Hi Evgeny

Is it any better way to resolve conflicts on editing same record in two different apps with briefcase?
In the moment I having like one app trying to override on apply update what was changed from another one , which is what it suppose to happens :slight_smile:
Say
app1 -> have old value on Qty field = 1
app1 -> have new value on Qty field = 5
app2 -> have old value on Qty field = 1
app2 -> have new value on Qty field = 10
app1 -> apply updates and updated Qty = 5
app2-> apply updates and updated Qty =10
app1 -> refresh Qty =10

what I’m trying to do to fix it:
I have one field for one appID , and writing Qty in this appID field, and having Total Qty as calculated based on summary of appID_Qty but because , database updates records by record , not by exact field , all one given record fields getting overwritten.

What I was thinking about if I can put business rule that will let update one taken app with appID only corresponding field name = appID , just wonder how it helps with briefcase scenario?

Why you can’t calculate Total Qty in trigger of DB?

You can add Qty into BusinessProcessor.UserUpdateFields so it will be considered as PK and you will have
app1 -> have old value on Qty field = 1
app1 -> have new value on Qty field = 5
app2 -> have old value on Qty field = 1
app2 -> have new value on Qty field = 10
app1 -> apply updates and updated Qty = 5
app2 -> try to apply updates with Qty =10. it will fail because Qty <> 1
app2 -> user should correct Qty

I can calculate Total Qty in trigger of DB , it’s good idea, but what about briefcase:

  1. I have to calculate Temp Total Qty if app status = disconnected
  2. Say if app1 was disconnected for 5 min and then trying to push Delta to overwrite that fields that were written by app2.

In a bad case scenario let this will be 10 items that were edited with app1 and app2 at the same period of time?

May be it’s possible to recognise computer ID or AppID on the server side ( good thing that I have only limited apps, say 5 ) and have trigger ( if I can pass that parameter by trigger, may be something like: ‘on last update identity field’ ) that will roll back fields that does not belongs to to that App1 or App2?