It's tricky.
You say you have debt owners and you have to repay quite a few. Ideally, this uses a withdrawal pattern and you avoid iteration altogether. I realize this is not always feasible. In cases like airdrops there can be a strong desire to use a use "push" process to send a batch of transactions. I'll assume there is a good reason.
On the contract side
You can iterate over a list of distributions and log success/fail as you go. You will want to use .send() so the whole process isn't held up by a single failed transaction. Since the sender has control of batch size, this is a case where you can use arrays for input and unbounded iteration. The sender can determine the optimal batch size. This is more gas-efficient than a purist approach insisting on one .send() per signed transaction.
The client is likely a server, but could be a browser, etc. Let's assume server. I mentioned earlier that the contract should emit success/fail while it thunders ahead undeterred by send failures. What to do with the send failures is a client-side concern, perhaps retry, perhaps a withdrawal pattern, perhaps give up. I merely assume the server needs to be informed.
On the sender side
A less obvious concern is nonce management. Whether batches or single transactions, to get significant volume through, the server and blockchain will probably use an asynchronous interface. That is, the server won't wait for confirmation before sending the next transaction. Consider deliberate throttling.
The server won't know the transactions were successful until sufficient confirmations are received. So there's the success/fail event and waiting for (10?) confirmations before declaring victory. I have found it's also important to have the ability to recall transactions that are overdue (maybe the gas was too low). You need to "recall" to have positive confirmation that the transaction is indeed failed and not merely indeterminant. This, so the server can confidently try again and be certain the end result won't be two payments to the same recipient.
In practice, this leads to a server that is tracking its pending transactions and their nonce perchance to emit a cancellation with the same nonce.
With so many pending transactions floating about, the client-side (say, geth) nonce is not reliable. Same for Infura. Pending transactions are subjective from the node perspective and a miss by even one will result in various errors and jam up the process.
In the end, you probably set up a singleton nonce counter of your own based on the idea that the sender is most qualified to know what was sent. More on the technical issues of infrastructure for this over here: Concurrency patterns for account nonce
Hope it helps.
I'll assume there is a good reason- the only reason that we do iterated payment instead of a single payment is gas cost, as calling the function once per debt-owner is going to cost a lot more (and we may have a lot of debt owners). – goodvibration Jan 20 '19 at 08:53You will want to use .send() so the whole process isn't held up by a single failed transaction- that was indeed my initial thought (which I have also explained in the question). However, I've just realized that a single transaction can, in fact, impact the rest of the process (thus denying the remaining debt-owners from receiving their funds). What if... a malicious user just loops forever and spends all the gas?sendwill not revert of course, just returnfalse, but then, the iteration itself will be reverted due to out of gas. Am I wrong? – goodvibration Jan 20 '19 at 08:56onlyOwnerfunction to clear malicious users from the queue, but that would reduce the transparency of my system, as I could technically remove any user that I want. – goodvibration Jan 20 '19 at 08:59