0

I am working on a project involving financial transactions.

There can be any number of transactions coming in at the same time.

The problem is that, it seems as though, in a few cases, the transactions are being "mixed up", in an unpredictable way. I don't know if it's a result of our "bad" Lifestyle choices for Castle Windsor or there is other code causing it.

Would like to clear the air on Castle Windsor.

The logging shows that sometimes a particular request will be mixed up with a different response.

I know...Scares us too!

Main technology used is C# 4, Net 4.5, WCF, Castle Windsor

It is structured as follows:

  1. There are incoming transactions, so services should always be up
  2. There are 3 main services
  3. Service A - Singleton Lifestyle - instantiates a client to Service B using the ChannelFactory. Can spawn up to 3 threads. Note that container is of type Castle.Windsor.IWindsorContainer
container.Register(Component.For<IServiceA>().ImplementedBy<ServiceA>().LifestyleSingleton());
container.Register(Component.For<IServiceBFactory>().ImplementedBy<ServiceBFactory>().LifestyleSingleton());
  1. Service B - Singleton Lifestyle - uses a service reference, proxy client to Service C
container.Register(Component.For<IServiceB>().ImplementedBy<ServiceB>().LifestyleSingleton());
container.Register(Component.For<IServiceC>().ImplementedBy<ServiceCClient>().LifestyleSingleton());
  1. Service C - Singleton Lifestyle - connects externally to some API
container.Register(Component.For<IServiceC>().ImplementedBy<ServiceC>().LifestyleSingleton());

+-----------------------+              +-----------------------+                  +-----------------------+
|                       |              |                       |                  |                       |
|                       |              |                       |                  |                       |
| [WCF Service  A]      |              | [WCF Service  B]      |                  | [WCF Service  C]      |
| Instantiates a        +------------->+ Instantiates a        +----------------> | Connects to an external
| client to B using     |              | client to C using     |                  | RESTful API           |
| ChannelFactory        |              | a serivice referece   |                  | (Singleton Lifestyle) |
| (Singleton Lifestyle) |              | to C                  |                  |                       |
|                       |              | (Singleton Lifestyle) |                  |                       |
|                       |              |                       |                  |                       |
+-----------------------+              +-----------------------+                  +-----------------------+

Update 1

Now going through a related SO question, and in the mean time will try out all suggestions carefully

Community
  • 1
  • 1
tinonetic
  • 7,751
  • 11
  • 54
  • 79
  • 1
    can u paste your code how do you inject classes to your service and registeration part. are you using wcf facility ? – ahankendi Nov 20 '16 at 12:17
  • Hi @ahankendi. Whilst, I appreciate your effort to help, I believe the code won't be material to the question, as the question has to do with my lifestyle setup with the services I have... `WCF A with channel factory client to B` -> `WCF B with service reference proxy client to C` -> `WCF to the internet` – tinonetic Nov 20 '16 at 12:22
  • 1
    Can I clarify, please? So when you say service A is a singleton, does this mean that you have configured service A to run in InstanceContextMode.Single?. Or do you mean that the client channel service A uses to call service B scoped as a singleton? Similarly, for service B. Is Service B configured with instance context is singleton or is the service reference service B uses to call service C scoped as a singleton? Or both? – tom redfern Nov 21 '16 at 09:57
  • You are creating the proxies as Singletons? That's a bad idea for many reasons. If you test with Transient do all your problems go away? – ErnieL Nov 22 '16 at 03:16
  • 1
    Hi @TomRedfern. Sorry for the late response. I realise I was not very clear. I have updated the question with a snippet explaining what I did... I guess ahankendi may have been right afterall... :) (gave him an apologetic +1) – tinonetic Nov 22 '16 at 06:15
  • @EnieL. Would you mind explaining why it's a bad idea? Just tried googling it but didnt have any luck on getting an explanation... in the mean time, I will try out transient and see how it goes – tinonetic Nov 22 '16 at 06:40

1 Answers1

1

Your problem could be that you have single instances of each service being used from multiple threads, concurrently. Any instance level state, whether it be in your code or your service architectures' (such as a call context, for example) will be shared and edited by all calls to the service. As mentioned in the comments, a Transient lifestyle will help, but there are also lifestyles available specifically for WCF, such as PerWcfOperation.

Andy Lamb
  • 2,151
  • 20
  • 22
  • What if we don't share/reuse state?The reason why we had chosen `Singleton` was(we believe) to address our main concerns `1) the resource expense of start-up`... & ... `2) the requirement to be always available`... We could be wrong, but that was the final reasoning after quite a lot of fighting. My other suspicion (in hindsight) is that the `Singleton` lifestyle choice means we have to be able to recover from a faulted state...which (I read) can be made possible through the [WCF Facility](https://github.com/castleproject/Windsor/blob/master/docs/wcf-facility-refresh-channel-policy.md). – tinonetic Nov 22 '16 at 16:29
  • If your services were reentrant (no shared state in application, infrastructure, or hosting code) I doubt you'd be seeing the problem you're describing, but I couldn't say for sure without digging deeper into your code. Are you sure using a `per call` lifestyle will lead to performance problems? If not, I'd keep it simple to start with and only optimise for performance if and when a bottleneck has been identified. – Andy Lamb Nov 22 '16 at 17:49
  • I understand. We will try all suggestions. Performance unfortunately, is a key requirement because it is a transactional application, working with set response time benchmarks (`ms`) that cater for all legs of the overall transaction...The resource expense on startup is expected to be high because of various components that (we knew from onset) have to be present to maintain integrity...not to meaning to bore you though... – tinonetic Nov 22 '16 at 19:46
  • Marking this as the answer as it is closest to the solution we used and the fix – tinonetic Mar 16 '17 at 06:30