silkapp / rest

Packages for defining APIs, running them, generating client code and documentation.
http://silkapp.github.io/rest
390 stars 52 forks source link

Acid-State example #143

Closed ronslow closed 8 years ago

ronslow commented 8 years ago

Is it possible to provide an example of integration with Acid-State?

hesselink commented 8 years ago

What kind of integration are you looking for? It looks to me like you could just run any kind of acid-state transactions you want inside of a rest API.

ronslow commented 8 years ago

Hi Erik

Just an example of a Handler which executes a query on an AcidState container

I'm finding the types quite difficult to manage.

Robert

On Tue, Dec 8, 2015 at 9:59 AM, Erik Hesselink notifications@github.com wrote:

What kind of integration are you looking for? It looks to me like you could just run any kind of acid-state transactions you want inside of a rest API.

— Reply to this email directly or view it on GitHub https://github.com/silkapp/rest/issues/143#issuecomment-162836919.

hesselink commented 8 years ago

I'm no expert on acid-state, but it looks like all the top level operations (query, update) are in IO. Since rest handlers run in MonadIO, I would think that using liftIO should be enough. So something like:

liftIO $ query acid SomeQuery

You'd need to get the AcidState from somewhere. The easiest thing is probably to run your rest handlers in ReaderT AcidState IO. Then at the top level of your application, you'd initialize acid-state, and call runReaderT api acid to pass it to your api.

Does that make sense? If it doesn't, can you paste a small example of what you're trying somewhere, together with the error message where you can't make it work?

ronslow commented 8 years ago

Thanks Erik

Yes, I thought that I would simplify as much as possible with respect to the tutorial by using mkResourceId but this in fact led to greater complexity in matching types between Rest and Acid-State.

I have followed the tutorial more closely, using mkResourceReader, and as you say this uses a ReaderT to allow Acid-State to play in IO:

resource :: AcidState Diary -> Resource IO (ReaderT BookingId IO) BookingId Void Void resource diary = mkResourceReader { R.name = "bookingid"

                                                         , R.get = Just

(getBooking diary) }

getBooking :: AcidState Diary -> Handler (ReaderT BookingId IO) getBooking diary = mkIdHandler jsonO $ _ bid -> liftIO $ query diary (GetBooking bid)

For the moment I am simply passing the AcidState as a parameter, but of course eventually this will be better to pass in by of ReaderT

Robert

On Tue, Dec 8, 2015 at 10:17 AM, Erik Hesselink notifications@github.com wrote:

I'm no expert on acid-state, but it looks like all the top level operations (query, update) are in IO. Since rest handlers run in MonadIO, I would think that using liftIO should be enough. So something like:

liftIO $ query acid SomeQuery

You'd need to get the AcidState from somewhere. The easiest thing is probably to run your rest handlers in ReaderT AcidState IO. Then at the top level of your application, you'd initialize acid-state, and call runReaderT api acid to pass it to your api.

Does that make sense? If it doesn't, can you paste a small example of what you're trying somewhere, together with the error message where you can't make it work?

— Reply to this email directly or view it on GitHub https://github.com/silkapp/rest/issues/143#issuecomment-162840240.

hesselink commented 8 years ago

Ah, I see! The ReaderT I meant wasn't the one constructed by mkResourceReader. That creates an additional layer containing the id of the resource being server. I was talking about the top level monad (the m in the top level Resource you're defining). In the tutorial this is always assumed to be IO. But it doesn't have to be, and I think in your case it should be ReaderT AcidState IO. Then the code under "running it" would be slightly different: instead of apiToHandler' liftIO api, it should be something like apiTohandler' (liftIO . flip runReaderT acid) api.

But your current method should also work, it's just a bit more explicit about passing around the AcidState. Are you still having problems, or does it work now?

ronslow commented 8 years ago

All working, thanks Erik.

On Tue, Dec 8, 2015 at 11:51 AM, Erik Hesselink notifications@github.com wrote:

Ah, I see! The ReaderT I meant wasn't the one constructed by mkResourceReader. That creates an additional layer containing the id of the resource being server. I was talking about the top level monad (the m in the top level Resource you're defining). In the tutorial this is always assumed to be IO. But it doesn't have to be, and I think in your case it should be ReaderT AcidState IO. Then the code under "running it" would be slightly different: instead of apiToHandler' liftIO api, it should be something like apiTohandler' (liftIO . flip runReaderT acid) api .

But your current method should also work, it's just a bit more explicit about passing around the AcidState. Are you still having problems, or does it work now?

— Reply to this email directly or view it on GitHub https://github.com/silkapp/rest/issues/143#issuecomment-162860078.

hesselink commented 8 years ago

Great!