Fork me on GitHub
#pedestal
<
2016-12-20
>
joshjones04:12:23

How is an interceptor fundamentally different from a handler, other than the format of "context" versus "request/response"?

joshjones04:12:36

My service needs to make a call to another service which could take anywhere from 500ms to 1000ms, and I want to go async instead of blocking and tying up threads. Should the call to the 3rd party service go in an interceptor, or in the handler?

ddeaguiar14:12:52

@joshjones Handlers are special case interceptors that operate on request maps and return response maps. I typically create Interceptors for things like validation and any other pre-processing needed for request handling. Refer to http://pedestal.io/reference/interceptors for more info

ddeaguiar14:12:57

If the implementation requires some sort of post processing (i.e., transformation, etc...) I'd probably implement the 3rd party call in an interceptor, put the result on the request map and perform the transform of the result in a handler.

ddeaguiar14:12:08

Using channels for async

ddeaguiar14:12:57

I'd also prefer thread vs the go macro because the backing thread pool used by the go macro is limited

ddeaguiar14:12:45

Hope this helps!

kirill.salykin14:12:00

@ddeaguiar is it possible to share such interceptors (validation etc)?

kirill.salykin14:12:19

@ddeaguiar I mean, can you please share them? 🙂

ddeaguiar14:12:36

I can create an example if I don't have any I can share

ddeaguiar14:12:08

But think of it this way, these are the same operations you'd perform in ring middleware

ddeaguiar14:12:32

The neat thing about interceptors is that you have access to the interceptor chain and you can manipulate it

ddeaguiar14:12:45

dynamically add/remove interceptors

ddeaguiar14:12:53

You can't do that with ring middleware

ddeaguiar14:12:14

@kirill.salykin The Pedestal docs site includes an example of an interceptor that performs request pre-processing (http://pedestal.io/reference/interceptors). The db-interceptor associates a db to the request. In that example, the database value is stored elsewhere in a global var.

ddeaguiar14:12:01

attach-database provides a similar example

kirill.salykin14:12:16

I am just looking for the good intereceptor + validation db interceptor seems simplier to me 🙂

kirill.salykin14:12:26

would really approciate if you can share it with me

ddeaguiar14:12:43

Ok, I'll dig something up and ping you sometime near EOD EST

lellis14:12:16

Hi everybody, im gonna start implement security in my pedestal app, is friend the best framework to do that?

ddeaguiar15:12:15

I've had good experiences with both using Pedestal

joshjones16:12:23

Thank you @ddeaguiar for the info. Since the 3rd party request will take maybe 500ms and our processing will take significantly less time (probably 30-50ms max), it somehow feels strange to put the 3rd party request in an interceptor, when it will take much longer than the actual handler — but it’s what makes sense, I think, if I’m reading you correctly.

ddeaguiar16:12:19

I think you can do it in a handler. Just return a channel

joshjones16:12:26

Potentially dumb question about pedestal — since the handler is the last “interceptor” to run, and it takes a request and returns a response, how to I do post-processing on the request? The interceptors seem to be pre-processing, but they work with context maps, and the handler works with req/resp maps. So how can I post-process the response map?

ddeaguiar16:12:50

Interceptors support :enter and :leave operations

mtnygard16:12:56

@ddeaguiar @joshjones Handlers can't return channels, but interceptors can.

mtnygard16:12:09

The channel must deliver exactly one context map.

ddeaguiar16:12:12

@mtnygard ah, thanks. Was fuzzy on that.

mtnygard16:12:25

After the context map is delivered, then the rest of the :leave functions will be called as normal

joshjones16:12:35

But I thought the :leave operation accepts a context map, and returns a context map — not a request or response map

mtnygard16:12:26

@joshjones That's right. When a handler returns a response map, Pedestal just attaches that response map to the context map, then starts calling the :leave functions with the updated context map.

joshjones16:12:45

Fantastic, that clear it up, thanks @mtnygard

mtnygard16:12:16

You're welcome!

joshjones16:12:55

Our app currently serves a few thousand requests per second, and I’m trying to improve latency by going async and hopefully pedestal will help with that — I think the best thing for me to do here is to write a simple app that utilizes the functionality of some of these pieces, and then I’ll be better informed to ask questions 🙂

mtnygard16:12:01

Just keep in mind that there are two ways to return a channel:

mtnygard16:12:27

1. If the interceptor returns a channel instead of a context map, then that channel can only deliver 1 value, which must be the new context map. That's the "async" case.

mtnygard16:12:12

2. If the interceptor returns a context map with a response whose body is a channel, every value delivered by that channel is streamed to the caller. That's the "streaming" case.

mtnygard16:12:48

Your description sounds like the async case, so you're on the right track.

joshjones16:12:09

excellent, I will use that as a guide :thumbsup::skin-tone-2:

marciol19:12:56

Hi guys, I saw that are several ways of building routes on pedestal, this could be verified on this test file: https://github.com/pedestal/pedestal/blob/master/service/test/io/pedestal/http/route_test.clj

marciol19:12:35

So my question is, how I choose the better way to express the routes of an application, is there a guideline?

mtnygard20:12:55

Hi @marciol! The different flavors of routing syntax are there because we've had some "evolution" over time. The "verbose" syntax is not something that anyone should write by hand. It is the most expanded form, mainly intended for internal use by the routers. The "terse" syntax is good if you need to express a deep tree of routes and you want to take advantage of "inheritance" down the tree for interceptors. For most uses, I would steer you toward the "table" syntax. It is the easiest to read and write, at the cost of some redundancy from row to row.

marciol20:12:57

Hi @mtnygard my gut feeling sayings that the table syntax is better for most cases, thanks

mtnygard20:12:19

Well, speaking as the person who designed the table syntax, I'm happy to hear that!