You are not logged in.
Hello ab,
Do you happen to know some details about FoundationDb, which powers the major part of Apple's cloud?
As I understand it, it's an open source transactional, distributed, and highly fault-tolerant key-value data store system.
What makes it different it's its "layer" concept - it allows other data layer, for example, a document database, a SQL database or any kind of database, to be built on top of it.
The potential integration with mORMot is to let mORMot have a distributed database backend with UNLIMITED space!
When Apple open sourced FoundationDb I spent hours reading about it and I was very attempted to make a post here
And recently Apple open sourced a Record Layer built on top of FoundataDb, I finally made this post ![]()
Oops...
I myself use ToClientDataSet() to convert from TSQLTableJSON to TClientDataSet.
You can also check TSynSQLTableDataSet and \SQLite3\Samples\ThirdPartyDemos\EMartin\TSynRestDataset\SynRestVCL.pas to see which suites your needs.
I think your code is logical and OK.
Please full text search into the mORMot library path for the various forms of the 'ToDataSet' function scattered around several units.
Try DateTimeToSQL instead.
A related discussion is here: https://synopse.info/forum/viewtopic.php?id=4909
@mpv,
Both the server and client are on Windows, and with the original post I meant cancelling the sockets on the client side.
@pvn0,
That's a bunch of helpful info and links you have provided, that gives me the direction for a possible solution for the issue! Thank you very much!
Assume a record class has a RawUtf8 field which might contain 10MB of string data.
Now the client calls Retrieve() in a background thread to get the record from a remote server.
The question is is there a way to interrupt/abort that http request operation in the middle of the network transfer process? Something like the TIdHttp.OnWork event hanlder, as demonstrated here (https://stackoverflow.com/a/6923250/133516).
Please note I'm not asking about how to terminate my thread, because that thread is waiting for 10MB of data to be downloaded and it cannot respond your 'Terminate' call until the download is completely finished or time out.
@MC,
I suggest you to create a new pull request at https://github.com/synopse/mORMot/pulls so that ab can review it.
While defining TDynArray as record/object saved you from writing try...final block, one the other hand, if it's implemented as class, one can easily inherit from it and add new functions.
Do I need to modify TECC* objects to handle large files ?
If so, do you have any suggestions or recommendations ?
Could my changes be added to the mormot framework ?
Good idea! May be use memory mapped file? I think ab will accept your changes if you don't break any compiler supported by mORMot ![]()
Instead of Declaring your property as a dynamic array, you can declare it as RawUTF8 and use TDynArray.SaveToJSON/LoadFromJSON.
Hello pvn0, thanks for your good advise! I see TDynArray has the Sort method, so it definitely meets my requirements!
PS:
My currently planned solution is to define a child class from TRawUTF8ListHashed (which are stored as JSON text in the db according to the document, since it derives from TRawUTF8List) for storing int64 values, for example:
type
TInt64ListHashed = class(TRawUTF8ListHashed)
public
Add(aValue: Int64): PtrInt; overload;
IndexOf(aValue: Int64): PtrInt; overload;
end;and use this type as the field type.
Hello ab,
According to the document (https://synopse.info/files/html/Synopse … ml#TITL_26), any TSQLRecord-derived fields those are defined dynamic arrays, I guess including TInt64DynArray, will be **stored as BLOB format** in the database.
With the current implementation, is it possible (maybe via a setting) to store TInt64DynArray as JSON text value in the db?
That can introduce a lot of benefits, for example, one can take advantage of the JSON1 SQLite extension, one can view the values in plain text so makes debugging issues easier, and so on.
Sounds very cool!
FYI:
A comprehensive test suite for RFC 8259 compliant JSON parsers: https://github.com/nst/JSONTestSuite
I came across this and thought I'd post it here.
It means we expect a single connection to the database.
...
Our SynSqlite3 wrapper serialize all operations via a lock.
Hello ab, out of curiosity, when sqlite is configured to allow multi connections, does it also use a lock to coordinate the multiple access, or does it have a better approach than locking?
How about SimpleEncrypt?
We use signals and fpPause for this
Signal interception https://git-pub.intecracy.com/unitybase … m.pas#L270
Signal handler https://git-pub.intecracy.com/unitybase … m.pas#L261
Main thread https://git-pub.intecracy.com/unitybase … m.pas#L557
Hello mpv, interesting, I assume you mean (https://www.freepascal.org/docs-html/rt … pause.html)
Do you know similar things exist for Delphi for Windows ![]()
Hello ab,
When you execute the following queries with SynDBExplorer.exe (sample 12), there will be no result. Maybe the framework need some adjustments for the 'pragma' keyword?
pragma compile_options; // with or without the semi-colon.Oh yes, did a code search and found that I also use that approach you illustrated ![]()
The following works perfectly for SQLite for me, but since mORMot persists datetime fields as ISO8601 I think it most probably also works with MS SQL.
function GetDateTimeRangeFilteringSqlClause(const aFieldName: String; const aStartTime, aEndTime:
TDateTime): String;
begin
Result := Result + FormatUTF8('(%>="%" AND %<="%")',
[aFieldName, DateToIso8601(aStartTime, True), aFieldName, DateTimeToIso8601(aEndTime, True)]);
end;Does it mean we can now use https://swagger.io/tools/swagger-codegen/ to generate, for example, JavaScript client library that can talk to your mORMot rest server?
If you read the mORMot documents, ab, the developer of mORMot, advocates DDD (domain driven design).
However, DDD involves a series of concepts which you have to grasp, and today I came across a short stackoverflow.com answer that can give you a big picture of DDD, so I couldn't resist to share with you guys:
Happy new year! AGO and all!
Thanks for sharing your experience about a real life mORMot-based project Yes, I have faith in ab and mORMot.
I have a POS software powered by mORMot and it's been so stable that now I'm wondering if the client hesitates to pay the maintenance feed for this year, happy or not? That's a question...
No problem, repository created.
checked out and starred, thank you!
Great to hear that!
Ah yes! Discovered log entries such as "SetThreadName 000026BC=TSQLHttpServer 80/root THttpApiServer". Thanks.
@ab,
Done as you instructed, see attached screenshot, not sure how to interpret the names...
And I explored the source and found:
constructor TSQLRestThread.Create(aRest: TSQLRest;
aOwnRest, aCreateSuspended: boolean);
begin
...
if fThreadName='' then
FormatUTF8('% %',[self,fRest.Model.Root],fThreadName);
...
end;So is TSQLRestThread.Create where the mORMot server threads are created and named?
Thanks.
Thanks for sharing, would be great if put it in a github repository ![]()
Great! Thanks for your quick reaction, as aways ![]()
But how the mMORMot threads are named? Do they have a fixed prefix or something like that? I did a quick look at the source without a successful finding... Thanks.
Assuming in a desktop program we have a mORMot server and a bunch of clients.
There will be 2 types of background threads in the program:
A - the server threads started by mORMot server when serving client requests.
B - the other ordinary threads started by the program.
The question is how to distinguish A from B?
I need this info to make sure the mORMot engine will log ONLY errors caused by the engine /db itself, but not errors caused in my other ordinary threads, by utilizing `SQLite3Log.Family.OnBeforeException`.
This is kind of a continued discussion of To allow ignoring exceptions with code, but I decided to post it separately to make things clearer.
Thanks.
...If it was me I would just let it blow up with an exception...
Agreed! Exception is such a godsend for handling errors!
@alpinistbg,
I agree with you about that 'one should resort to first trying to find the source of the errors instead of just checking for if Self := nil'. ab might has his opinion based on the new replies here... In a perfect world (which is non-existence) I also wish ab stop using the 'with' keyword, but that's another question ![]()
Also need to consider - maybe there is another case where those 'if self = nil' guard clauses have reasons to stay - mORMot is a framework, and the clients (the code that the users of mORMot write) might be some mess multi-thread code and cause 'self = nil' to happen?
IIRC, although it's unclear about that, but actually sample 22 is outdated - it uses SpiderMonkey24 and it's deprecated by @MPV and their team.
The latest is the wrapper for SpiderMonkey52, you should look at <mORMot_root>\SyNode\Samples
ab wrote:A class instance being nil happens.
Yes, it happens. But it shouldn't be used. It is a programming error. A big one.
Why do you think so? It's not a programming error but a very good programming technique called "Guard Clause" which makes the program reliable and clear to read.
ref1: https://en.wikipedia.org/wiki/Guard_(computer_science)
ref2: https://medium.com/@scadge/if-statement … 219a1a981a
A article related to the fact that self might be nil: http://blog.marcocantu.com/blog/when_self_is_nil.html
Also notice one of the comments:
"I've actually seen self = nil a few times, especially
in multi-threaded code. I have a couple methods that
start with ". -- Jim McKeeth
What a great contribution, mpv!
And for those didn't know about Unix Domain Socket:
A Unix domain socket or IPC socket (inter-process communication socket) is a data communications endpoint for exchanging data between processes executing on the same host operating system. Like named pipes, Unix domain sockets support transmission of a reliable stream of bytes (SOCK_STREAM, compare to TCP). In addition, they support ordered and reliable transmission of datagrams (SOCK_SEQPACKET, compare to SCTP), or unordered and unreliable transmission of datagrams (SOCK_DGRAM, compare to UDP). The Unix domain socket facility is a standard component of POSIX operating systems.
I heard about valgrind for the first time, what an amazing tool and what an amazing you've done!
Yes, as far as I know at least several forum member did, including me, and I posted a link to a working tutorial. Please search the old forum post.
The problem lies into TSQLDataBase.TransactionBegin() method, which detects the active transaction and instead of throwing an exception like "Can't nest transactions", it surprisingly rollbacks the transaction and begins a fresh one! IMHO this is extremely insidious, because it prevents me (developer) from detecting that something is wrong with my code (yes, it is) and throws away all changes made so far without any clue.
I haven't dig into the source of TransactionBegin, but if what you described is true, it definitely has a room to improve.
@alpinistbg, I replied you in the post you mentioned above.
Right. MSSQL can fail in some spectacular ways. But in most cases the reason is returned back to the caller.
I order to handle such a fail, the caller must to *know* the reason. The batch may fail because of duplicate PK, unique index, I/O error, etc. Different failures have different resolutions. In case of mORMot I don't know the exact reason because it is not marshaled back correctly. (I've got a text like "batch broken because of ...")
I totally agree! The actual database error messages must be transferred back to the the caller (the mORMot clients)
Even If I know that acquiring the transaction failed, I can't replay the batch, because its content is already cleared. I think it is quite trivial to preserve the contents, even the batch is closed for further modifications, and just to add a "BatchResent" method for example. It is matter of few lines of code, IMHO.
This can be achieved by using a standalone TSQLRestBatch, but I'm not sure if TSQLRestBatch is serializeable/unserializeable.
Further, I think the constant of 2000 ms for begin transaction timeout is very optimistic and it should be much more than that. Also, some (exponential) backoff must be provided into the retrying loop. We're dealing with RDBMS with limited transaction capabilities and locking resolution (not versioning).
Agreed, the 2-second timeout should be customizable.
Please, explain me the right way to contribute to the project. Should I post patches here with a proper explanation, or, to make a branch in a repository to make changes there? Have you adopted some procedures for collaboration, etc.
I believe you can contribute via a github pull request (https://github.com/synopse/mORMot/pulls … s%3Aclosed), or do something like the OP here: https://synopse.info/forum/viewtopic.php?id=4795
@alpinistbg,
I have complete going through all your 3 posts related to these issues related to the client-side batch operations.
The issue
===
I have a POS program which completely relies on the client-side, UOW batch operations, and I had an issue that's almost identical to yours - it happened during a multi-db to central-db syncing process which is implemented using batch process.
When the batch update failed, I found mystery error messages in the log file: "Error SQLITE_ERROR (1) [Step] using 3.15.1 - cannot rollback - no transaction is active, extended_errcode=1", followed by a "TransactionBegin timeout" error .
From the error message I have no clue about what actually went wrong, until many months later, it turned out to be a primary key violation (you know, syncing from many branch db to a central db).
The cause of the error revealed when I have the actual data from the client and running the server-side software in the IDE.
I don't know why neither the mORMot engine log nor the caught exceptions didn't tell me the actual database error messages, otherwise I should have identified the error much much earlier.
But after that, the software which's powered by mORMot has been running for years without issues.
My thoughts
===
- It's a must for ether the server-side log or the BatchSend to tell the actually database system error message, I prefer BatchSend should return the actual database error code and message.
- As @alpinistbg has found out the 2-second timeout for starting a transaction should not be hard-coded - at least it should be customized via a property.
- To implement a retry-able client-side batch update, maybe we can do this:
a, before calling BatchSend, make a copy a the TSQLRestBatch instance.
b, if BatchSend failed, make sure the db is rolled back. @ab, how can the clients get to know this?
c, we can now retry executing BatchSend using the backup copy of TSQLRestBatch we saved earlier.
Agreed!
@Erick, I'll be willing to buy your ebook when I actually start using EWB (at least when it's code complete feature is ready.
I wish so. I have briefly tried several versions of both Elevate Web Builder and SMS, and I prefer Elevate Web Builder very much, for 3 reasons;
- Its document for the UI framework seems to be completed.
- It's much stable in my experience (just maybe less than a hour of trying).
- It's UI framework is focused on Desktop screenshot size but not mobile screen size.
I'm waiting for their addition of the code-complete feature.
So it'll be definitely a great great great thing if mORMot supports generating wrapper for Elevate Web Builder .
You are welcomed! I'll try my best to get mORMot prosperous ![]()
The most probable way of hosting a mORMot server on Linux for production is using a Reverse Proxy, and for this purpose Nginx might be the first choice.
I came across this online (and open source) tool for generating nginx configuration snippets, and there is a section for setting up reverse proxy:
hope it helps.
Thanks! I was just waiting for this after seeing the commit of the new FishShop sample, because I'm interested in learning how to make my program running as a system service under both Windows and Linux ![]()
Google recently introduced , it's well explained how it works here:
I believe with mORMot we can definitely implement a similar queue-based architecture!