You are not logged in.
Good point.
It will also make compilation faster.
Thanks @ab for all this detailed information,
So I can't imagine a good use of packages - specifically speaking for mormot.
Especially a new version where the need for updates tends to be more constant.
What I have done on the contrary is to create a big executable which is able to be run as several services. Then it is faster to setup and update, and the OS will definitively share memory for code.
Interesting. For "several", how many are you referring to approximately?
Several microservices running on the same machine can benefit from packages or not?
I believe that the memory consumption - of the sum of all - will decrease.
But starting from a certain number of executables, because for few it will have the opposite effect.
Thanks @ab, @mdbs99
Reported in 2018.
Has it been fixed in recent versions of FPC?
In any case, it would be interesting to put this in the mORMot documentation.
And recommend the win32 version.
Confirming, problem solved when cross compiled from Win32 -> Linux X64
Thanks again for the tip!
Yes, I am making a cross compiler, Win64 -> Linux 64.
I didn't know about these problems.
I will try to make this Win32 -> Linux cross compilation and report the result here.
Thanks for the informations.
I'm not sure if it's related, but I'm having a strange behavior with float values in json.
Occurs only on Linux.
When compiled for Windows 64 this is ok.
Lazarus + FPC with recommended versions.
V := _Json('{"value":99.99}');
with _Safe(V)^ do
begin
writeln(SynCommons.DoubleToStr(D['value']));
//write 2.1426169135105198E-13
end;Thanks, so you create also html/mustache templates using VS codium? To clarify, I'm looking for a friendly web IDE development, like we can do forms in Delphi.
I don't like visual editors. They usually create dirty HTML code.
In addition, they may not work in conjunction with widget frameworks.
But I believe there are extensions for vs code/vs codium that add WYSIWYG editor.
NOTE: When I created this topic, TMS was creating a WYSIWYG editor for TMS WebCore, which was an extension for vs code.
But I don't know how this project is doing at the moment.
A pure html/javascript client reduces or even eliminates the need for an MVC server.
The mORMot server would be serving the API only.
Another option is to create a separate server, to serve HTML, which also consumes the API on mORMot server.
The Boilerplate HTTP Server based on mORMot is very interesting for this purpose.
https://synopse.info/forum/viewtopic.php?id=3365&p=1
You have to test the GetValueByPath() result, or use another method to check if it exists.
I already do this verification with VarIsEmptyOrNull.
Or try to avoid with _Safe(J.Value['a']).U['d']
I am quoting to check if there is any inconsistency or not.
If it's correct, then it's ok.
So null is converted into 'null', but also 'null' is converted into 'null'
In the context of the example above, null is converted to an empty string.
Please ignore the a.c example
The question is this:
If the property exists but is null it returns an empty string.
writeln(VariantToUtf8(J.GetValueByPath('a.b'))); //write "" (empty string)
If the property does not exist (undefined in javascript) it returns "null" as a string.
writeln(VariantToUtf8(J.GetValueByPath('a.d'))); //write "null" (string with "null" content)Note that a.d does not exists.
Considering this example:
J := _Safe(_Json('{a:{b:null,c:"null"}}'));
writeln(VariantToUtf8(J.GetValueByPath('a.b'))); //write "" (empty string)
writeln(VariantToUtf8(J.GetValueByPath('a.c'))); //write "null" (string with "null" content)
writeln(VariantToUtf8(J.GetValueByPath('a.d'))); //write "null" (string with "null" content)If the property exists but is null it returns an empty string.
If the property does not exist (undefined in javascript) it returns "null" as a string.
Wouldn't it be more appropriate to return an empty string in both cases?
I agree with pvn0.
I cannot shutdown the service, even after this period, if the client already was using the service before
If there is information that will only be on instance A and that cannot be continued on instance B, is this not a type of session?
macfly wrote:But if server A is no longer receiving requests after a while, why would someone still be using it?
"I cannot stop the service even if just one person is using it, because I cannot control if this client got the new URL, from the database, to use the instance-B."
Okay, now I think I understand.
You return the URL at the beginning of the session and it will be the same until the client is finished.
In theory a client can stay for hours in the same session and you would not be able to make this replacement within a constant period.
You can end up with hours of delay if the client remains open.
I cannot guarantee that a service is always online, 100% of time, if I can shutdown someone that are using it because I supposed that no one was using.
Don't you agree?
But if server A is no longer receiving requests after a while, why would someone still be using it?
Yes, I understand what you want to do.
But if server A is no longer receiving requests for a certain period, wouldn't it be safe to terminate it? Why wait for the mORMot service to report that is idle.
For example, a time of 5 minutes after you have redirected requests to server B will be enough so that server A is not doing anything else.
Actually, what you want to do is finish the application, right?
Ending threads being executed by the application will not allow the executable to be replaced.
I mentioned above that I save the time that connection was last requested and renew before reaching the timeout.
So this problem does not occur in my case.
The question is whether this would apply to mORMot.
I don't know if in mORMot there is a way to intercept when the connection is requested.
That it was I meant when said "...if no client sent a request, you can't be able to remove any other inactivity connection", i.e., first you need a request then you could do other things like renew connections.
Yes, in my scenario, with on-demand verification, the connection is renewed per thread.
One thread does not interfere with the connection of the other, including renewal.
But is this a problem? What error could occur if a connection that is not being used is idle on a thread that is also not in use?
@mdbs99
I do not use mORMot in this application. I use a persistence layer that I created myself.
There is a method that requests a connection whenever necessary, so I don't need a timer. It occurs on demand.
If there is no activity for a while, the connection will die, but on the other hand it is not being used.
When a new request occurs, its expiration will be checked and if it is expired it is renewed.
In the case of mORMot is need to analyze how and when the connection is requested, - but I believe that it will not be possible to do the same.
In this case the timer would be better.
At least in my case, I don't care if next request will be the first that will create all threads again, as all were gone eventually. Does mORMot can do that?Yes, this is the question.
You will have to dig deep into the code and tests to see how and when threads and connections are created and released by mORMot.
In my connection pool I store it when it was last requested.
This allows you to recreate the connection by inactivity, and by demand.
But I don't know if this would work in this case.
You have to check where and when the connection is requested by mORMot.
In any case, it may be easier to implement a timer to check the expired connections in the pooll, instead of checking and releasing the threads.
Interesting.
My connection pool is not much different.
The difference is that I don't use a threadvar.
I maintain a list of connections indexed by the thread id.
When starting the thread the connection is created for your id.
At the end of the thread I destroy the connection by id.
Good to know about this solution.
I have a legacy application, where I created a connection pool.
Each thread has its own connection.
But this application is not using mORMot.
Out of curiosity, when is the datamodule destroyed?
Is automatically destroyed when the thread ends?
@mdbs99
What I wanted to exemplify is that if I need to format in a fixed format I can create a variable with the values already defined.
If the goal is to avoid name collision, we don't need class vars. It is important to keep things simple.
If I need commonly used parameters, I can create a variable / object for this.
PT_BRFormatSettings = .... // Filled with the appropriate configuration
S: = TSynStr.Format (S, PT_BRFormatSettings);
// OR
S: = SynFormat (S, PT_BRFormatSettings);NOTE: I'm not talking about proprietary code, but the framework code, which IMHO should be as simple and straightforward as possible.
Doesn't it take more work to locate these possible collisions, and create the overloaded methods, than just adding the prefix?
Even if a collision list is created, further collisions may occur in the future.
With a prefix everything is solved. No ambiguity, no additional work afterwards.
S: = SynTrim(s); // No doubt which method is being usedS: = Trim (s); //SysUtils.Trim? SynCommons.Trim? overloaded / not overloaded?I may be mistaken, but I think I've seen something related to mormot + pas2js done by @warleyalex.
Shouldn't these methods be static? (class methods)
Or your suggestion ist to maintain a global instance of the created objects?
TSynString = object
public
class function Trim(const aValue: RawUTF8): RawUTF8;
end;I use bpl here too.
An advantage of DLL is that it does not force you to compile with the dependency on runtime pakages.
But, if you are compiling the exe and the DLL with the dependency on runtime packages, any advantage of the DLL is lost.
@mdbs99
Yes, I know about this possibility.
But I don't know if it's good practice.
I think it adds unnecessary complications.
I am referring, that as it will be a new version of the framework, there is not so much problem in changing the name of all classes to prefix with TSyn.
Many have already changed and the refactoring is inevitable.
If it were a change in a production framework I would agree that it would be unnecessary.
But it is a new version where other changes are already being made that will force refactoring.
So the time to change is now, after it is released it will no longer make sense...
A common prefix makes the class's origin easily identifiable.
In code and elsewhere.
For example, anyone who sees a question on the stackoverflow about http communication and sees something like:
Cli: TIdHTTPEasily identifies that indy is being used.
+1 TSyn for all types.
TSynRTTI, TSynOrm, TSynRest, TSynInterface, TSynService, TSynNet
ADO components are not thread safe.
Each thread must have its own connection.
I believe that it will not be a simple task to use ADO in conjunction with Mormot, due to the need to have this thread-connection control.
Following the post to see what ab says about it.
At first glance I also found it strange.
But considering that ORM alone is already an abbreviation that defines the concept of the class, I believe it makes sense.
And as the convention is maintained, the name of the final class will not be changed.
TORMCustomer = class(TORM)
TORMCustomer = class(TORMRecord)
TORMCustomer = class(TORMAnything)
//We will have TORMCustomer anyway.If you use a DocVariant you can do the validation.
There are methods that allow you to check if a property exists, extract the properties and check if there is a new one, etc.
You do not need to stop using the Records you already have. After validating you load in to Record.
You could also do this validation once a hour/day so as not to overload the system.
I use a lot of statisc methods.
For example, my routines for handling strings are in a TStringUtils object.
An advantage, is that it forces you to specify the object avoiding ambiguities of functions with the same name in different units.
In the case of mORMot, I even always identify the unit in the code to avoid any ambiguity.
S := SynCommons.Trim (S);Has many functions that simplify everything in SynCommons and I always take a look.
But I didn't really know about this TrimControlChars function.
But based on what it does the name shouldn't be RemoveControlChars? ![]()
I think this replace will be safer if you consider only #13 as a line break as well.
pdf := docs._[i].S['pdf'];
pdf := StringReplaceAll(pdf, #13#10, '');
pdf := StringReplaceAll(pdf, #13, '');NOTE: The order matters. You should replace #13#10 first, and then #13
Really!
Even for those who do not use the framework it is a good reference material.
I believe that in case of authentication error (not token expiration), you should inform the user about it. And allow him to log in again.
You should not store your username and password locally.
I use both methods suggested by @vitaly.
A check in expiratron time. And also on demand.
Having the ability to renew on demand is important in cases where the token may expire due to a change in the user's account.
*Speaking in a generic way and not just in APIs created via mORMot.
Example, i use APIs where a change in the user's account (password, e-mail, etc.) causes the token to expire.
So just observing time of expiration is not enough.
But you have to be careful not to create an infinite loop in this check.
@Vitaly
Oh, forget it.
Got it really wrong.
The question is about the client ...
Sorry about the mess.
Is it safe to renew the token automatically?
In the APIs that I use and implement, the renewal of the Token is the client responsibility.
If a request is made with an expired token, the server only rejects the request. Then the client must renew the token again.
![]()
Jokes aside, it's good to see Embarcadero mentioning mORMot.
It would be better with an example of use in the video.
(Perhaps because they did not find the components of mORMot in the palette? Nooo, I did it again!)
Embarcadero took the first step.
Now "someone" needs to create an twiter account... ![]()
What is the base type of TAbstractPerson?
TSynAutoCreateFields manages the instances for you, but in this case the container object must be a TSynAutoCreateFields, that is "TPerson".
TPerson= class(TSynAutoCreateFields)
protected
FDocs: TDocs;
published
property Docs:TDocs Read FDocs; //TSynAutoCreateFields manage this field
end; If you cannot leave TPerson as TSynAutoCreateFields then I believe that you should destroy the objects explicitly in the Destructor, Destroy method.
Wouldn't this cause you problems later when using this class?
You will have to check the instance whenever you need to get the value.
if person.docs is TDocsPJ then..
else if person.docs is TDocsPF then...What if you create a field to define the type of document?
TDocType = (dcCPF, dcCNPJ, dcRG, dcCNH);
TPerson= class(TAbstractPerson)
protected
FDoc: RawUtf8;
FDocType: TDocType;
published
property Doc:RawUtf8 Read FDoc write FDoc;
property Doc:TDocType Read FDocTypewrite FDocType;
end; Tried to use the forum Search feature?
I think I've seen that same question and the solution more than once...