In my project I am using <cfmail> to send an order confirmation to a user after successful creation of an order. I have got one doubt. If the mail server goes down during that time is there any way to handle that situation with cftry and cfcatch, or doesn't it handle those errors?
Normally if spoolenable is enabled the email will go to the spool and the page processes whether the mail actually gets sent or not as long as all the required fields are entered and valid.
https://wikidocs.adobe.com/wiki/display/coldfusionen/cfmail
Spool Enable details from Wiki
spoolenable
Optional
Whether to spool mail or always send it Immediately. Overrides the ColdFusion Administrator Spool mail messages to disk for delivery setting.
yes: saves a copy of the message until the sending operation is complete. Pages that use this option might run slower than the ones that use the No option.
no: queues the message for sending, without storing a copy until the operation is complete. If a delivery error occurs when this option is No, ColdFusion generates an Application exception and logs the error to the mail.log file.
Related
We're doing everything we can think of to limit the number of complaints we receive and will immediately remove anyone who marks us as junk that does not need to receive our emails. However, the last handful of complaints we've received have come from transactional emails of people who are receiving our company's services and NEED to receive everything we send transactionally as a critical part of our service. (e.g. We are booking their travel on their behalf and we need to send them verification emails to confirm their booking details.)
We're assuming that most of these complaints are somehow either false positives or are being done on accident. One customer confirmed that they did not click the junk mail button but it ended up in their junk folder and they moved it to their inbox. Some questions:
Can a TiS complaint be triggered by any means other than the user manually marking an email as junk in their email client? (Can automatic spam filters trigger this complaint? AWS documentation specifies only clicking the junk button.)
Besides contacting each individual personally, what would you suggest we do? Our complaint rate is continuing to rise even though we are taking action on every one.
I have a system like this:
Node reads events off a queue.
A notification email is sent based on the event, using AWS SES.
The scenarios where issues can arise are:
Some other node may also read a duplicate copy of the event in parallel, and thus now 2 emails are sent.
Node 1 reads the event, makes the 'send email' call and then dies without acknowledging the sent email. Node 1 doesnt know if the email was sent or not, so it resends after coming back up.
How do i ensure the email is sent only once?
I believe scenario 1 is generally handled by most modern queueing systems. I think there are other questions that address locking issues like that better, so I'll ignore it for the time being.
Regarding scenario 2, most modern queueing systems deal with the same issue - it basically comes down to a question about how you want to fail.
For instance, if you had to choose between delivering the email twice, or not delivering it, which would you choose? In queue parlance, this is described as at-least-once vs. at-most-once delivery.
For these answers, I'm assuming a queueing system like RabbitMQ which enables acks and timeouts.
Option 1 - Delivering the Email Twice
Attempt to send the email, and if successful, ack the message to the queue. Setup the queue so that un-acked messages are re-added after a timeout. In this case, if a failure occurs during sending, no ack will occur, and the message will be re-sent to the queue, then picked up again. Now, if there is a consistent failure with the ack (but not your email), you could end up in a situation where you keep sending the email. The majority of the time, however, this shouldn't be a problem.
Option 2 - Not Delivering The Email
Setup a queue without ack's. This is generally more performant, so that's a plus. The queue worker will take a message from the queue and attempt the email. If an email fails to send, it won't be retried.
For many of the services I work on (this doesn't apply to email, but does apply to writes to a DB), I try to make them idempotent, then just go with the first option. In the worst case, you churn on writes, but hopefully you have logging to detect this.
I'm writing service layer for DDD app.
Services are exposed through JSON-RPC over WSS.
I'm not sure how to respond to redundant calls to service.
Some facts about the system:
All requests must be completed within specific time or timeout exception occurs.
If system is under heavy load it may decide to discard request (visible as timeout).
If system is under heavy load some messages may expire in the queue (visible as timeout).
Even if request reaches it's destination ACK may not reach user in
time (visible as timeout).
End user has right to re-invoke method if ACK didn't arrive in time.
No guarantees on request completion are given.
Thus the need for idempotency.
Problem arises if we consider [4]+[5] implications:
User invokes method setFoo(Bar).
Entity was created but ACK didn't make it on time.
User receives timeout and assumes that he should try again, so he re-invokes setFoo(Bar).
Entity already exists -> hmm...
Question is: Should user get ACK or Error(I've already done that mate...)?
An idempotent operation should have the same behaviour when it is called multiple times. This suggests that the return value should be the same as well, so in the scenario you are describing above, the user should get ACK.
Consider the alternative; if you return an error to the user, then how should the user respond? What "error handling" is appropriate?
You can make an argument for a response of ACK(I've already done that mate...) but the part in brackets should be a purely optional informative field, not something that affects how the user processes the response.
i have wrote a Text Message Sender Program via JMS with C++ following.
tibems_status status = TIBEMS_OK;
status = tibemsMsgProducer_SendToDestination(
m_tProducer,
m_tDestination,
m_tMsg );
Suppose status == 0, this means only that Function has worked succesfull. It doesn't mean that my Text Message was sent succesfull
How can I ensure that my Message was sent succesfull? Should I get a ID or Acknowledge from JMS Queue back?
It depends on the Message Delivery Mode.
When a PERSISTENT message is sent, the tibemsMsgProducer_SendToDestination call will wait for the EMS server to reply with a confirmation.
When a NON_PERSISTENT message is sent, the tibemsMsgProducer_SendToDestination call may or may not wait for a confirmation depending on if authorization is enabled and the npsend_check_mode setting. See the EMS docs (linked above) for specific details.
Lastly, when a RELIABLE_DELIVERY message is sent, the tibemsMsgProducer_SendToDestination call does not wait for a confirmation and will only fail if the connection to the EMS server is lost.
However, even in the situations where a confirmation is sent, this is only confirmation that the EMS server has received the message. It does not confirm that the message was received and processed by the message consumer. EMS Monitoring Messages can be used to determine if the message was acknowledged by the consumer.
The message monitoring topics are in the form $sys.monitor.<D>.<E>.<destination>, where <D> matches Q|q|T|t, <E> matches s|r|a|p|\* and <destination> is the name of the destination. For instance to monitor for message acknowledgment for the queue named beterman, your program would subscribe to $sys.monitor.q.a.beterman (or $sys.monitor.Q.a.beterman if you want a copy of the message that was acknowledged).
The monitoring messages contain many properties, including the msg_id, source_name and target_name. You can use that information to correlate it back to the message you sent.
Otherwise, the simpler option is to use a tibemsMsgRequestor instead of a tibemsMsgProducer. tibemsMsgRequestor_Request will send the message and wait for a reply from the recipient. In this case you are best to use RELIABLE_DELIVERY and NO_ACKNOWLEDGE to remove all the confirmation and acknowledgement messages between the producer and the EMS server and the EMS server and the consumer.
However, if you do go down the tibemsMsgRequestor route, then you may also want to consider simply using a HTTP request instead, with a load balancer in place of the EMS server. Architecturally there isn't much difference between the two options (EMS uses persistent TCP connections, HTTP doesn't)
Producer -> EMS Server -> ConsumerA
-> ConsumerB
Client -> Load Balancer -> ServerA
-> ServerB
But with HTTP you have clear semantics for each of the methods. GET is safe (does not change state), PUT and DELETE are idempotent (multiple identical requests should have the same effect as a single request), and POST is non-idempotent (it causes a change in server state each time it is performed), etc. You also have well defined status codes. If you're using tibemsMsgRequestor you'll need to create bespoke semantics and response status, which will require extra effort to create, maintain and to train the other developers in your team on.
Also, it far easier to find developers with HTTP skills than EMS skills and it's far easier to find information HTTP that EMS, so the tibemsMsgRequestor option will make recruiting more difficult and problem solving issues more difficult.
Because of this HTTP is a better option IMO, for request-reply or for when you want to ensure that that the message sent was processed successfully.
Imagine 3 system components:
1. External ecommerce web service to process credit card transactions
2. Local Database to store processing results
3. Local UI (or win service) to perform payment processing of the customer order document
The external web service is obviously not transactional, so how to guarantee:
1. results to be eventually persisted to database when received from web service even in case the database is not accessible at that moment(network issue, db timeout)
2. prevent clients from processing the customer order while payment initiated by other client but results not successfully persisted to database yet(and waiting in some kind of recovery queue)
The aim is to do processing having non transactional system components and guarantee the transaction won't be repeated by other process in case of failure.
(please look at it in the context of post sell payment processing, where multiple operators might attempt manual payment processing; not web checkout application)
Ask the payment processor whether they can detect duplicate transactions based on an order ID you supply. Then if you are unable to store the response due to a database failure, you can safely resubmit the request without fear of double-charging (at least one PSP I've used returned the same response/auth code in this scenario, along with a flag to say that this was a duplicate).
Alternatively, just set a flag on your order immediately before attempting payment, and don't attempt payment if the flag was already set. If an error then occurs during payment, you can investigate and fix the data at your leisure.
I'd be reluctant to go down the route of trying to automatically cancel the order and resubmitting, as this just gets confusing (e.g. what if cancelling fails - should you retry or not?). Best to keep the logic simple so when something goes wrong you know exactly where you stand.
In any system like this, you need robust error handling and error reporting. This is doubly true when it comes to dealing with payments, where you absolutely do not want to accidentaly take someone's money and not deliver the goods.
Because you're outsourcing your payment handling to a 3rd party, you're ultimately very reliant on the gateway having robust error handling and reporting systems.
In general then, you hand off control to the payment gateway and start a task that waits for a response from the gateway, which is either 'payment accepted' or 'payment declined'. When you get that response you move onto the next step in your process and everything is good.
When you don't get a response at all (time out), or the response is invalid, then how you proceed very much depends on the payment gateway:
If the gateway supports it send a 'cancel payment' style request. If the payment cancels successfully then you probably want to send the user to a 'sorry, please try again' style page.
If the gateway doesn't support canceling, or you have no communications to the gateway then you will need to manually (in person, such as telephone) contact the 3rd party to discover what went wrong and how to proceed. To aid this you need to dump as much detail as you have to error logs, such as date/time, customer id, transaction value, product ids etc.
Once you're back on your site (and payment is accepted) then you're much more in control of errors, but in brief if you cant complete the order, then you should either dump the details to disk (such as csv file for manual handling) or contact the gateway to cancel the payment.
Its also worth having a system in place to track errors as they occur, and if an excessive number occur then consider what should happen. If its a high traffic site for example you may want to temporarily prevent further customers from placing orders whilst the issue is investigated.
Distributed messaging.
When your payment gateway returns submit a message to a durable queue that guarantees a handler will eventually get it and process it. The handler would update the database. Should failure occur at that point the handler can leave the message in the queue or repost it to the queue, or post an alternate message.
Should something occur later that invalidates the transaction, another message could be queued to "undo" the change.
There's a fair amount of buzz lately about eventual consistency and distribute messaging. NServiceBus is the new component hotness. I suggest looking into this, I know we are.