Architecture for passing messages from one system to another - c#

I am starting to work on a piece of development today, and was looking to see if this is the optimal solution:
I have 3 systems:
SystemA : third party system which handles order management.
SystemB : internal system used for shipping orders that have been placed on systemA for a particular supplier (used for shipping old suppliers orders)
SystemC : internal system used for shipping orders that have been placed on systemA for a particular supplier. (used for shipping new suppliers orders)
So systemB and systemC both need to pull orders from systemA but only want to pull orders based on a systemID, which is fine.
Goals:
1. Avoid Duplication of orders sent to old (B) and new (C) systems
2. speed
3. Allow for new systems to be added
I plan on building an intermediary service the retrieves orders from systemA using BL that I already have written. From there it will add it to a queue. System B and C will them make a web request to some endpoint using their system ID to get their latest messages for their system. Each system can them process the messages/orders and import them into their systems.
So my questions:
Would masstransit or nservicebus work in this situation?
IS there an example of this sort of thing anywherE? I could not find one?
Does this structure sound ok or would there be a better way to do it?
Would I be better using a table queue and WCF to acheive this?

Related

Orleans. Akka.net. Problem with understanding the actor model

If you don't know C# but you are familiar with the actor model please read my problem below as it is more about architecture and data management.
I'm a very junior C# developer and trying to understand what the actor model is. I'm kind of done with it but it's left one point that I cannot get.
Before I tell you a problem let me describe the context in order to provide you with better undersrtanding.
As a test example I want to build an app for an imaginary bank. I'm going to implement this application by using both akka.net and Orleans on learning purpose and to be able to compare them.
Use cases:
As a user I want to be able to create a new account;
As a user I want to be able to login to the app using my account unique number;
As a user I want to be able to deposit money to my account;
As a user I want to be able to select another user and transfer a specified sum of money to their account;
As a user I want to be able to withdraw a sum of money from my account.
So, there are the following entities:
User;
Account.
Identifying one to one relationship between the user and their account.
I'm going to use ORM to store this data in my Database. Obviously the models look something like this:
public class User
{
public Guid Id { get; set; }
public string FullName { get; set; }
....
}
public class Account
{
public Guid Id { get; set; }
public string UniqueNumber { get; set; }
public string Balance { get; set; }
...
}
And I also want to have two actors/grains:
AccountActor;
TransactionService;
Their interfaces:
//Or IAccountGrain
public interface IAccountActor
{
void Deposit(Money amount);
void Withdraw(Money amount);
}
//Or ITransactionGrain
public interface ITransactionActor
{
void Transfer(IAccountActor from, IAccountActor to, Money amount);
}
The thing that I don't understand is how to treat the data in the relation database.
Let's imagine the following scenario:
50 users are online and vigorously making request via the client app to the REST API of the app.
They are withdrawing, depositing and transferring money almost without any pauses.
The question is:
Should I create one actor per user account? I'm pretty sure that I
need because how then I can implement thousands of transactions
between different accounts.
How can I associate the user account with the AccountActor? Is it correct If I load the data from database using repository before
actor's activation/start and set up the state?
And the main problem:
How to save state back to the database?
Let's image an account A that has 1000$.
And It occurs about 100 transactions initiated by the users where this account is involved.
Account A changes its state from message to message.
What is the best approach to save these changes to database? I read that If I use calls to the database directly from the actor, I will lose all the benefits because of blocked operations.
Should I create one more actor to process messages from other actors and writes changes to database using repositories?
I mean I can send from AccountActor messages about the account changes to the new actor where I will call the appropriate repository. But, Isn't it a bottleneck? Let's imagine 1000 users online and about 100 000 transactions between accounts. Then the actor that is responsible for saving accounts changes to the database can have too many messages to process.
Sorry for the long text. I tried to find examples of applications that use Orleans or Akka.net but I haven't found anything what utilizes a database.
Thank you for you attention.
There are a couple ideas you’re missing here, but let’s take the questions in order.
Should I create one actor per user account? I'm pretty sure that I
need because how then I can implement thousands of transactions
between different accounts.
I assume the alternative you’re considering is multiple actors per user account, and this would be wrong. There can be only one actor per user account or else you will run into the problem you describe that simultaneous requests can withdraw the same money twice.
How can I associate the user account with the AccountActor?
You are missing a UserActor which owns the AccountActors. An account cannot exist without an owner, otherwise we don’t know who owns the money in an account. In the real world, one typically does not send money to a random account. They want to send it to a person, and uses the senders User persona account to do so.
Is it correct If I load the data from database using repository before
actor's activation/start and set up the state?
Yes, in fact that is mandatory. Without the state in the actor, the actor is not good for much.
What is the best approach to save these changes to database? I read
that If I use calls to the database directly from the actor, I will
lose all the benefits because of blocked operations. Should I create
one more actor to process messages from other actors and writes
changes to database using repositories?
You’re on the right track but not quite there yet. Saves of actor state are done with asynchronous methods to write to the DB. With an async method, the main thread does not block waiting for the DB write to happen, thus the processing thread can continue with its business.
When only one actor is involved in an action, it can save its own state via the async method. In banking registers there are always 2 accounts involved and writes to both must succeed or fail, never one succeed and one fail. Therefore, the TransactionActor will open a DB transaction and tell each AccountActor to save its state using that DB transaction. If either fails, it aborts the transaction and both fail. Note that this method is a private async method on the TransactionActor so you get the benefits of parallel processing.
BTW, you can't find any examples of writing to the DB in Orleans because that is all handled for you by the framework. The save methods are automatically async and they interact with the DB. All you do in Orleans is reference the Actor and the state is automatically pulled from the DB for you.

UCMA recording app

I've installed a MSPL script to redirect INVITE audio messages to the UCMA sip address
I'm currently writing a UCMA app for Skype for Business to:
receive incoming calls
accept the call
create a conference call
add a trusted participant to the conference
create a recording instance on the trusted participant audio flow to record the conversation
The last thing I need to do is add the To caller URI to the conference call.
I've tried to invite the new participant into the conference using the code examples from this article, but I get an exception saying there are no AvailableMediaTypes in the conversation.
public static async void InviteToConference(string destinationUri)
{
//Create a new conversation for the application endpoint.
_toConversation = new Conversation(_server.ApplicationEndPoint);
var conferenceInviteSettings = new ConferenceInvitationSettings();
conferenceInviteSettings.ConferenceUri = _conferenceUri;
ConferenceInvitation invitation = new ConferenceInvitation(_toConversation, conferenceInviteSettings);
try
{
await invitation.DeliverAsync(destinationUri);
}
catch (InvalidOperationException)
{
// Conversation was terminated while trying to add participant.
}
}
Can someone please show me what I need to do to add / invite a participant into a conference call?
It would be even better if someone could show me how to record a Skype for Business call without the need to create a conference, as a conference can't be forwarded.
Your code looks like the old way (UCMA 3) of doing it. Have you tried this.
e.g.
McuDialOutOptions mcuDialOutOptions = new McuDialOutOptions();
mcuDialOutOptions.ParticipantUri = "sip:alice#contoso.com";
mcuDialOutOptions.ParticipantDisplayName = "Alice";
mcuDialOutOptions.PreferredLanguage = CultureInfo.GetCultureInfo("en-us");
conversation.ConferenceSession.AudioVideoMcuSession.BeginDialOut("tel:+14255551234", mcuDialOutOptions, dialOutCallback, state);
Using this sort of method to record very specific and low traffic should be fine but when you start to scale it up then you are going to hit all sorts of problems.
As for how to do it without a conference:
There is no way to do it fully with the supplied Microsoft API's.
What you have to do is implement, buy or use open source libraries for the following pieces:
sniff network packets
decode RTP/SRTP streams
decode the audio and/or video codecs used between the callers
encode streams into your desired format and save somewhere
To get access to the SRTP streams encryption setup and to figure out what the dynamic payload types for the audio/video codecs used, you also need to know the SDP offered and answered between the calling parties. You also need access to the SIP traffic to determine the calling parties to know who called who. This can be a lot more trouble than what it seems...
To get the SIP/SDP information there are two options that I know of:
Skype/Lync Server SDK (MSPL / Server Application) to see most of the SIP traffic. This is what I've used to implement a recording solution.
Skype/Lync SDN SDK - I haven't used this API but it seems to give access to the SDP so it should work.
If you get all these peices into place then the next problem is you can only "record" (basically "sniff") what you can see. If you can't see the RTP/SRTP traffic you can't record the calls.
So you need to have the sniffer part of the recording software on areas of the network that see the traffic you want to record. For example if you wish to record all PSTN calls, you can have a network spanning port off the Skype mediation servers.
If you wish to record ALL calls, then that gets a lot harder. You most likely need to either:
Force all media trafic to go through a known place (like the Edge server) and put sniffers on the that network.
Have lots of sniffers in strategic areas of the network to capture most RTP/SRTP traffic.
The problems with the above solutions are:
Forcing all the traffic through one point can cause performance issues (like you will see with your conference setup) once load starts to increase. Also forcing external (edge server users) and/or federated calls through this one point can cause a problems. Think edger server user calls to edge server users where the media traffic may not even go into your network at all but live only on the internet. Forcing the trafficing into your network can cause performance issues.
When not forcing all the traffic through one point, you may never be see all skype user to skype user calls depending on your network setup. Calls between Edge server skype users are even more of a problem as the media traffic may not even enter your network at all.
On top of all that there are the general problems of storage management (recording after a while will start taking up a large amount of disk space) and call recording management (e.g. searching for a specific call) and user security around these recordings to deal with. I'm sure I'm missing a lot but those are the basics.
If recording in not going to be a core component, you could just buy a 3rd party call recording solution that supports Lync/Skype.

Multiple clients using redis cache

I have a question concerning redis in a distributed architecture.
Assume I have n clients, either windows desktop applications or asp.net web/web api servers.
One of the clients, lets say client A, hits the cache for a data and has a miss (the data is not in the cache). The client then starts to get the real data (from lets say a database) and then sets it in the cache when it's done.
Client B comes along and wants the same data, does a fetch to the cache and since it's a miss, does the same processing.
Is there a way for Client B to ...(N) not to do the processing (i.e go to the database) until the data is in the cache and fetch the data from the cache instead when it's available?
I understand that on a single app (or web server), using threads it's easy to check that, but in a distributed architecture?
Is this also a correct way of thinking as well? for the wait process that is
If so then could Client A put a flag somewhere stating that he's loading Data X and that all other clients should wait until he's done?
Otherwise, the idea then would be something along the lines of :
Client A requests Data X
Miss in cache
Processes Data X
Looks if Data X is now in cache
If not, add Data X to cache, otherwise, use it and don't store it in cache
Thanks!
As Kevin said, it's called cache stampede.
One of the best documents to do with this problem I have read is Using memcached: How to scale your website easily (comes from Josef Finsel):
What we need in this instance is some way to tell our program that
another program is working on fetching the data. The best way to
handle that is by using another memcached entry as a lock.
When our program queries memcached and fails to find data, the first
thing it attempts to do is to write a value to a specific key. In our
example where we are using the actual SQL request for the key
name we can just append ":lock" to the SQL to create our new key.
What we do next depends on whether the client supports returning
success messages on memcached storage commands. If it does,
then we attempt to ADD the value. If we are the first one to attempt
this then we’ll get a success message back. If the value exists then
we get a failure indication and we know that another process is trying
to update the data and we wait for some predetermined time
before we try to get the data again.
When the process that’s updating
the cache is done, it deletes the lock key.

Tally database synchronization with c# Application

I want to make an application to sync Tally Sales Order and Sales Invoice from tally to our SQL Database. Currently for testing purpose I am using Tally ERP 9 Educational Version.
I have created some sales orders in tally and need all order with their details from tally using tally ODBC Sql query
uptil as per my research, I am getting few sales order details like Voucher Number,Order Date,'Voucher Type'.. etc. from tally ODBC table CompanyVoucher. but few details came empty, although related data exist in tally order. like Reference , Party Name ... etc.
Also, I am unable to find Tally ODBC table to get few other sales order related data like item name, item number , item quantity, rate and order total, order no etc.
Can anybody suggest SQL Query or Tally ODBC Table from where i can find these order related data. Also I am not sure, if we can not access these details due to Educational Version, and any limitations on Educational Version on access of these details.
so please suggest me on this.
Synchronisation is the process of replicating data between two or more computers using Tally.ERP 9 in a Client – Server environment. Data is transferred from the client to the server and vice versa. Tally.ERP 9 offers control over the frequency of Synchronisation i.e., data can be replicated after each transaction or updated at specific intervals.
Configure Server for Synchronization
To configure the Server Company for Synchronization, follow the steps given below:
Go to Gateway of Tally > F12: Configure > Advanced Configuration
In the Advanced Configuration screen,
Under Client/Server Configuration section,
Set the option Tally is acting as to Server, to run Tally.ERP 9 as Sync Server
Specify the required port number (e.g. 9009) in the Port field....
Tab down to Tally Sync Configuration section:
Set the option Ignore Clients modified Voucher Type Masters to No, so that modifications made to Voucher Type Masters on the Client are updated on the Server
Set the option Enable Sync Logging to Yes, to generate a Log file which contains synchronized vouchers and is saved in the Tally folder.
Set the option Truncate previous log before Syncing should be set to Yes, to allow the previous log file to be overwritten by the current log file.
Go to end and press Enter to save the details.
For the above changes to take effect, Tally.ERP 9 will prompt you to restart the application as shown:
Press Enter or select Yes to restart Tally.ERP 9 on the Server computer.
Tally.ERP 9 will restart and in the Information Panel you can see that it is configured as the Sync Server as shown below.
Detailed reference here.
If the datas are present and you cannot access the sync then there
must be restriction in your version

Custom Workflow Step - Retrieve Field From Entity

I have a workflow activity which I use to send out e-mails to suppliers on a regular basis and scheduling follow-up phone calls etc if there is no reply. However my problem is that I somehow need to retrieve the e-mail for each supplier before sending the message.
How can I go about retrieving the value in a specific field from a specific entity in CRM 2011?
Here is the pseudo-code:
For each supplier entity in the system {
if (sendSalesRequest) {
Send Initial E-mail
- wait 21 days
if (noReply) {
Send Follow up e-mail
- wait 7 days
if (noFollowupReply) {
schedule phone call activity everyday until reply
}
}
}
}
However, I need a way of retrieving the e-mail address from the suppler entity.
I'm not looking for a worked solution (though I wouldn't turn it down!), just guidelines on how to go about this task as I'm brand new to CRM development.
Thanks,
Tysin
If your new to 2011 I would suggest reading about the SDK. In particular you need to look at custom workflow activity development. It has a number of samples which should help you along the way.
I would suggest having:
A master workflow, that has a single step to call your custom workflow activity which processes the suppliers. You start this workflow whenever you want to process all the suppliers.
An on-demand workflow that sends the initial email
An on-demand workflow that sends the follow up email
An on-demand workflow that schedules the phone call
The reason I suggest this is that means you keep the creation of data in workflows where is it easier to manage and handle. E.g. you could change the email message without recompiling your custom workflow activity.
So first step in your master custom workflow activity, is to query Crm, I would suggest a QueryExpression to start with. That way you can get the data to base you logic on.
Then you need some code to start a workflow against a record, to send the email and phones calls. There is an example for this here.
Then you code would look a little like this:
QueryExpression query = new QueryExpression("supplier");
query.ColumnSet = new ColumnSet("sendsalesrequest", "noreply", "nofollowupreply");
EntityCollection entities = service.RetrieveMultiple(query);
entities.Entities.ToList().ForEach(entity =>
{
if(entity["sendsalesrequest"] == "Yes")
{
StartWorkflow(entity.Id, "Send Initial E Mail Workflow Name");
}
//etc
}
This is quite high level but should hopefully get you going in the right direction.

Categories

Resources