```// ktor client webSocketSession.send(frame)``` ...
# coroutines
u
Copy code
// ktor client
webSocketSession.send(frame)
this suspends until it's actually sent? or only until enqueued (and will be sent later)? if it's the later - is there a way to tell it's actually been delivered? -- I need to update my entity's state from
SENDING
to
SENT
y
The docs say:
Enqueue a frame, may suspend if an outgoing queue is full. May throw an exception if the outgoing channel is already closed, so it is impossible to transfer any message. Frames that were sent after close frame could be silently ignored. Note that a close frame could be sent automatically in reply to a peer's close frame unless it is raw WebSocket session.
While
flush
says:
Flushes all outstanding messages and suspends until all earlier sent messages will be written. Could be called at any time even after close. May return immediately if the connection is already terminated. However, it may also fail with an exception (or cancellation) at any point due to a session failure. Note that flush doesn't guarantee that frames were actually delivered.
So it seems there is no easy way to figure out if the frames were delivered or not, but
flush
guarantees they were sent at least
u
im using okhttp and in that case the
flush
is a no-op ehm
hm, it seems this is the way of doing websockets on clients in general so i must be missing something
d
The only way to handle this really would be to have your clients respond with some sort of ack so you can change the state on your side. Or perhaps your entities state graph can be changed, and SENDING vs SENT isn't as important a distinction.
u
One way with this "await matching ack" approach is, how long do you wait? network could suck and might take some time, right? say I arbitrarily choose 10seconds timeout, nothing is stopping ack coming at 11th second etc
d
Is there some reason you need that level of acknowledgment? At this point I would start questioning the requirements
u
which one do you mean, i need "message delivered" state in app, thats all basically
d
Usually the states then are “Sent/Pending” before the acknowledgment and “Recieved” after. If you design your protocol to have a nonce, then any unacknowledged message could be retried after a while, until you get an ack.
u
by received you mean by the server or the other party?
and Sent means received by server?
d
This is up to you (or your product) to decide.
u
> Usually the states then are “Sent/Pending” before the acknowledgment > how? how can client know if message was sent without ack?
d
That’s why it’s called “pending”
u
😀 okay, i meant the Sent case
d
Until there is an ack from the server, you can’t.
u
when would you then considered the message failed? never?
d
You can never be certain that the other side didn’t receive it, but you can indicate that you are certain they have received it.
So, pending until ack, sent when acked, error/warning on timeout, maybe with retry.
u
the thing about timeout that bothers me, imagine theres also binary frames in the protocol, and imagine a its 1GB in size(unrealistic but go with it) and since messages are queued, a simple message will have to wait its turn, and theres no way to tell when it's the simple message's turn (to start counting the timeout from)
tldr; timeout would include time in queue
d
Yep. So just leave it pending. Or break up the binary into smaller chunks so it doesn’t clog the queue.
u
So just leave it pending
for ever? as in dont have a error state?
d
I’m not your designer, that’s up to you.
u
😄 I'm asking what did you mean by that exactly
d
I’m saying it’s your decision on how you want to balance the tradeoffs.
u
what would you consider good?
d
I personally wouldn’t bother for v1. If my users found it to be an issue, I would then work out what was best for my users based on their feedback.
Remember, perfection is the enemy of the good.
u
sure, im just gathering opionons, they're nonbinding 😀