2

I have a class with many services that basically call Database connections (DBISAM or via ZEOS).

I am makinge this class available in a webservice like using TidHTTPServer. I am using the OnCommandGet Event from it and use the ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo to make the requests and results.

I have created a TObjectList to hold an instance of each client related to this service class. The connection to the database is created and freed for every call done, in a hope to not have thread problems.

I want to know if this is the proper way. I am not using session from the TidHTTPServer. Upon each service request I find out the object on the TObjectList that stores the info related to that connection.

I have looked over questions but I did not get all the information I need.

However I am not sure about the safety, specially when many calls can happen simultaneously. I have been using it regularly mostly 1 call per time, since is hard to test with many connections at same time.

I want to know if this is the right approach, or if not, how can I implement a "bridge" to safely call my class (I have created a QueryActivity on this class, mimicking the COM query style) passing request and returning the parameters.

Delphi XE2 - Indy 10.5.8

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
Eduardo Elias
  • 1,742
  • 1
  • 22
  • 49
  • This is not related to VCL – Sir Rufo Jul 05 '13 at 22:38
  • Encapsulate everything in a thread – Jerry Dodge Jul 05 '13 at 22:39
  • @JerryDodge All TIdHttpServer request are in seperate threads. There is no need to seperate them to another thread – Sir Rufo Jul 05 '13 at 22:40
  • @SirRufo Yes of course, but I mean all the business logic and handling of what's done in the server - as well as database connection, everything everything – Jerry Dodge Jul 05 '13 at 22:42
  • @JerryDodge You are talking about threadsafe. Threadsafe is to use an instance per thread or a single threadsafe instance (e.g. using TCriticalSection). This depends on the target resource. – Sir Rufo Jul 05 '13 at 22:47
  • 1
    @SirRufo Not sure how that relates, I'm talking just basic concept of encapsulating everything inside of its own master thread so it can be re-used, let's say, between a VCL Forms (Test) Application and a Windows Service Application, and perhaps an ISAPI server. – Jerry Dodge Jul 05 '13 at 23:19
  • @JerryDodge The question is about the server part, not the client. Also the question is not related to VCL. – Sir Rufo Jul 05 '13 at 23:24
  • @SirRufo Indeed, it is about the server, not the client. Not sure why you think I was talking about the client. And of course it's not related to VCL, I wasn't saying that either. I was just saying it's good practice to put everything in a thread which can be re-used. I didn't intend for it to be an answer, only a recommendation. – Jerry Dodge Jul 05 '13 at 23:48
  • I am calling my business code from the OnCommandGet, for every connection to the server made. My code is not using VCL, it is only business logic and selects and updates to the database, encapsulating on Json and return to the client. My question is: is it right? Can I put this code on this event? What will happen with few clients accessing at same time. I don't see this server running with thousands of connections, mostly less than a hundred. – Eduardo Elias Jul 06 '13 at 00:34
  • I'm working on a similar project, an HTTP server hosting information about the latest product versions, which has a SQL Server database behind it. What I have done: 1) built my own Client-Dataset object with some custom proprietary features, 2) encapsulated an ADO DB connection inside an object re-used in every thread which needs DB connectivity, 3) Created complex object structure which holds the real-time relevant version/update information as a global, updating periodically from DB, and 4) HTTP requests read from this object structure rather than from DB, providing JSON and file streams. – Jerry Dodge Jul 06 '13 at 00:56
  • This update server I'm working on is encapsulated inside a Windows Service Application, but I test it in a VCL app. I recognize application parameters which switch on the "test mode" application, otherwise it's by default a Windows Service. The point is, when everything is encapsulated inside a master thread, it can be re-used in different environments. – Jerry Dodge Jul 06 '13 at 00:59
  • Funny, a year later, I'm searching Google how to encapsulate an HTTP server properly, and come across this and read my old comments. Currently building a new system, same concept, just new methods of implementation. – Jerry Dodge Aug 07 '14 at 00:14

2 Answers2

4

Indy TCP server classes (as tTIdHTTPServer) have the option to assign a application-specific context class. This class contains connection-specific information about the client and can be extended with custom properties to carry your application specific information. To do this, create a subclass from TIdServerContext, and assign the class to the server's ContextClass.

If the connection is kept alive between requests (which is recommended to save resources), this context will keep the application-specific client information for its lifetime.

Indy also allows to iterate the list of all connected connection context, for example to support broadcast messages, or to collect information.

Examples on Stackoverflow:

How to track number of clients with Indy TIdTCPServer

Indy 10 TCP server

How do I send a command to a single client instead of all of them?

Community
  • 1
  • 1
mjn
  • 36,362
  • 28
  • 176
  • 378
1

Dealing with threads and therefore take care about threadsafe you always have to keep an eye on the targets.

Database

MultiUser Databases are threadsafe, SingleUser are not

Database Access Component

Some are threadsafe, some not. If you don't know, treat them as not threadsafe


In your case (hope you have a multiuser database) it is safe to use a connection/query instance per thread.

If you want to speed up your app use an ObjectPool for connection and query instances.

For testing purpose you can build a small client that performs a lot of requests in a loop and run multiple instances of this client.

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • Both Database Access components that I am using are thread-safe and used based on the rules I found in their documentation to make sure of it. – Eduardo Elias Jul 06 '13 at 00:29
  • +1 Not sure why the downvote but this is as simple as an answer could be to such a broad question. – Jerry Dodge Jul 06 '13 at 01:00
  • for HTTP server testing, simulating many clients, Apache Bench and Apache JMeter can be used, they also collect statistics, plot diagrams (JMeter), and are easy to use – mjn Jul 06 '13 at 08:54