dfordivam / reflex-websocket-interface

A simple to use interface for websocket using reflex-frp
GNU General Public License v3.0
19 stars 4 forks source link

Using the same underlying message type *seems* to cause infinite loop #7

Closed 3noch closed 7 years ago

3noch commented 7 years ago

My messages looked like this:

type WsRequest = ReqGetUsers :<|> ReqGetUser :<|> ReqPutUser :<|> ReqAddUser
data ReqGetUsers = ReqGetUsers  -- response type was RespGetUsers [User]
data ReqGetUser = ReqGetUser Int -- response type was RespGetUser (Maye User)
data ReqPutUser = ReqPutUser User -- response type was RespPutUser (Either Text ())
data ReqAddUser = ReqAddUser User  -- response type was RespAddUser (Either Text User)

Everything worked fine until I added that fourth message. After that I saw behavior where requesting either ReqPutUser or ReqAddUser would cause the app to go into an infinite loop and eventually crash. The first two messages still worked fine.

After many hours of trying to find the loop I tried one crazy idea. I removed ReqAddUser and once again ReqPutUser started to work. So I changed ReqAddUser to this:

data ReqAddUser = ReqAddUser () User

And suddenly all 4 of them started to work!

Could it be that because two messages carried the same type that some type-level encoding treated them the same? Then when trying to look for it, it would somehow look forever?

3noch commented 7 years ago

Actually this doesn't seem to be it. However, I did finally find a workaround.

For AddUser I try to construct the User type on the client side and send it. Whenever I do that, it loops. However, if I first pull a User down from the server and update it. I can send it back just fine.

Constructing the user type on the client causes the send to never even make it to the server, which means it must be looping while encoding the type.

3noch commented 7 years ago

I found the cause. If, after downloading a default user type from the server, I set its userCreatedUtc timestamp to UTCTime (fromGregorian 0 1 1) 0, the loop comes back. However, using some other time (like `UTCTime (fromGregorian 2017 3 12) 3333) works.