Episode Transcript
Transcripts are displayed as originally observed. Some content, including advertisements may have changed.
Use Ctrl + F to search
0:01
Welcome to another episode of the Mapscaping
0:03
Podcast. My name is Daniel and this
0:05
is a podcast for the geospatial community.
0:08
Today on the podcast we're talking about PG EventServe.
0:11
And to help me do that I've invited Paul Ramsey on
0:13
the show. So Paul Ramsey has been
0:15
on the podcast a bunch of times before. There'll
0:17
be links to all of the episodes he's participated
0:20
in in the show notes of this episode today so
0:22
we won't spend a great deal of time on introductions.
0:25
So you might be wondering what PG EventServe
0:27
is. Well it's a Postgres
0:30
SQL only event server in Go. It
0:32
does one thing and one thing only. It takes
0:34
events generated by the Postgres SQL
0:37
notify command and passes the payload along
0:39
to a waiting web socket client. And
0:41
it might just be the most useful small thing
0:44
Paul has ever written.
0:47
Hey Paul, welcome back to the podcast. Now you've
0:49
been on here a bunch of times so for
0:52
the listeners, if they haven't heard you already I'll
0:54
put a bunch of links in the show notes of this episode
0:56
so they can listen to all the great stuff we've
0:58
talked about before and interesting things you have to say.
1:01
But let's pretend for a second I've been
1:03
living under a rock and I'm brand new to the geospatial
1:05
world. I have no idea who you are. Would
1:07
you mind just introducing yourself briefly to the listeners please? Sure.
1:11
I am a developer of the PostGIS
1:13
spatial database and thus
1:16
someone who knows something about a little
1:18
bit about geospatial, a little bit about databases,
1:21
a little bit about the uses people put
1:23
those technologies to. Yeah, I like
1:25
that. Someone who knows a little bit. I
1:27
like that. A little bit about everything. Yes, I
1:29
am the ultimate dangerous man.
1:32
Yes. Okay. And
1:34
you've developed something else. It's something called PG
1:36
EventServe. Without going into heaps
1:38
of detail, heaps of background around PostGIS,
1:41
I'm assuming people have an understanding of what
1:43
that is now. If not, again, you've been
1:45
on the podcast before. There'll be a link to that in the show
1:48
notes. So let's dive in. What
1:50
is PG EventServe? What does it do? PG
1:52
EventServe watches for
1:55
listen slash notify events coming out of the
1:57
Postgres database and converts.
2:00
those events which are something
2:02
native of database world into events
2:04
on web sockets, which are native
2:07
to the web development world. And
2:09
to give that explanation, I have for most
2:11
users explained absolutely nothing. What
2:15
problem are we trying to solve here? Maybe we're
2:17
just not there. I think that's a good place to start.
2:19
The problem we're trying to solve is the problem,
2:22
and this is a problem which is more
2:24
native to maps
2:27
than it is non-mappy interfaces.
2:29
It's a problem that information in a
2:32
database can change, and
2:34
the people looking at that information might
2:36
have a gain of utility out
2:39
of being able to see that change. And
2:41
pushing that information out from
2:44
the database
2:44
to the people
2:46
with user interfaces can be
2:48
a fiddly thing. It turns out
2:51
that all the facilities to do that
2:53
trick exist in the database
2:56
and exist in the web technology world. And there has been
2:58
a gap in between them that needed to be filled,
3:00
and that's what PT event serve does. So on the
3:02
database side, there's this idea of listen
3:05
slash notify. It's a Postgres-only
3:07
feature. It doesn't exist in SQL Server
3:09
or Oracle.
3:10
But what it lets you do is
3:12
if you are a database
3:14
client, and that could be
3:17
really any software which connects directly
3:19
to the database, you can say, I
3:21
would like to listen to channel
3:24
five. And it's not five, it's actually a text
3:26
string, so it could be channel Daniel or channel sailboat.
3:29
But I want to listen to channel sailboat, and
3:31
that database client will, in addition
3:33
to the other things it's doing, have
3:36
a listen set on channel sailboat. Any
3:38
other database client can then say, or
3:41
the database itself can then say, I have a notification
3:43
for channel sailboat.
3:45
And at that point, every client who's listening
3:47
on channel sailboat will get that notification. It
3:49
is asynchronous, which is to
3:51
say it happens, actually, no, it's synchronous.
3:54
It happens immediately. The magic comes
3:56
when you start to hook up things
3:59
that happen in the database. base to this notification
4:01
procedure. So the easiest thing in the world
4:03
is to add a trigger to a table that
4:05
fires every time a row in the
4:07
table is updated or inserted
4:10
or deleted. So it's like the tables thing
4:12
you care about, anytime something changes, update,
4:15
insert, delete, a notification gets thrown.
4:17
Every client watching that channel then
4:19
gets an update that the table's changed.
4:22
Yeah, I just want to clarify a couple of things
4:24
here. The first thing, the client, are we talking
4:26
about like a QJX client, for example?
4:29
Or when you say client, what do you mean? Yeah,
4:31
it's good to clarify what I mean by database
4:34
client because pretty much anything
4:36
that looks
4:37
at data, anything you see on your screen is
4:39
at some remove a database client. But
4:41
I mean this in a fairly specific way. I mean
4:43
a piece of software which has attached to the database
4:46
using the databases specific
4:48
communication protocol and connection port. Very,
4:50
very technical. QJX, it turns out,
4:53
is a Postgres client in that
4:55
very narrow sense in that it literally connects
4:58
to the database directly using the Postgres
5:00
connection protocol. If you work with Postgres
5:02
yourself, you might have used like the PSQL
5:04
terminal monitor.
5:05
It too is a native connection.
5:08
And so it's quote unquote a database client. You'll
5:11
note I have not said like Chrome or
5:13
Firefox or web
5:16
anything. Because even though those interfaces,
5:18
those web interfaces vary very
5:20
frequently, almost always show data which
5:22
is residing in a database. They do never connect
5:24
directly to the database. They connect to
5:27
a web server. And the software
5:29
that's running inside that web server
5:31
may or may not at some point connect
5:33
directly to the database and ask questions of it. So
5:35
there's always this sort of there's this thing
5:37
that sits in between a
5:39
web client and the database. And
5:41
usually the thing that sits in between the web client
5:43
database just does stuff like ask for
5:45
a file, get a file back. We want to do something
5:47
different than that.
5:48
In order to get a web client
5:51
to update when the database table changes,
5:53
we need to somehow take that signal
5:55
that notifies signal which is coming out of the database
5:58
and convert it from something which.
5:59
standard database clients can
6:02
hear, to something which web clients
6:04
can hear. And that's what PG
6:06
EventServe does. It just sits in between.
6:09
And so you tell PG EventServe as a web client, hey,
6:11
I'm interested in Channel Sailboat. PG EventServe
6:14
sets up a native database connection on its side
6:16
to the database and says, hey database, I am interested
6:18
in Channel Sailboat. When the notification comes
6:20
up, PG EventServe gets on the database side,
6:23
flips it over and sends it
6:25
on to the website. And it does that using
6:27
a technology called WebSockets. Unlike
6:30
most web tech where the client is in control
6:32
and says, I want this file, give me this file. I'm
6:34
interested in stuff like this here. So this URL on the web server
6:36
gives it back.
6:37
With WebSockets, it's possible for the server to be
6:39
in control and to say, hey web client, here's
6:41
something new. And that's what happens. Now
6:44
for a banking app, or really almost
6:46
like any sort of form based standard
6:49
enterprise app, like the amount of data that someone's
6:51
looking at at any given time is practically
6:53
none.
6:54
So the odds that there's any utility
6:56
to being able to tell the clients, hey,
6:59
there's something that's changed, you need to update yourself, it's
7:01
relatively low. But
7:03
think about what a web map shows.
7:06
Like it's not infrequent for a given
7:08
web map panel to visually
7:10
be showing the end user
7:12
absolutely every single record in a table.
7:14
So if there's more than one user
7:17
and they're changing things, they're
7:19
almost always changing something that's visible within
7:21
the frame of the other users. And it makes
7:24
quite a bit of sense, again, depending on the app needs, for
7:26
that change to propagate immediately
7:29
and for every user to see it when it happens.
7:31
You're right that this makes a lot of sense, especially if
7:33
people are making decisions based on
7:35
what they're seeing in the frame of
7:38
the map.
7:38
Can you talk to me or just explain briefly
7:41
how this happens today because we're used
7:43
to maps updating. Could you explain that process
7:45
just before we dive into
7:48
listen notify and these triggers that you talked about in
7:50
just a little bit more detail? Right now if you see
7:53
a map self-updating, there's a strong
7:56
likelihood that it's polling and
7:58
there's nothing wrong with that. But that means. that
8:00
the control is still held by the
8:02
client. So it's getting updates
8:04
at whatever its polling rate is. If
8:07
it is in fact a truly
8:09
asynchronous
8:09
update based
8:12
system, it may have some quite
8:14
complex middleware in
8:16
the middle that's handling the web sockets and
8:18
maintaining
8:19
information about the state of the
8:21
system in the middleware, which
8:24
is again like a perfectly reasonable way to
8:26
solve the problem. And for problems of certain
8:28
scale of tens of thousands of moving objects
8:31
might be the only way to solve the problem.
8:33
The nice thing about centralizing the
8:35
model in the database and saying my understanding
8:37
of the state of the system is entirely
8:39
contained in the database tables is
8:42
that it is a modeling system
8:44
that still allows every single
8:46
piece of database connective software
8:49
to participate in it. It's not something bespoke.
8:52
It is something which still operates by the rules
8:54
of SQL. And in fact, my favorite trick in demonstrating
8:57
PGA
8:57
event serve to people is to get
8:59
them to look at either web
9:01
map or ideally both a web map and like a huge
9:04
service. And for me
9:06
to say one, two, three,
9:08
to write a little piece of SQL, which
9:11
updates the map object they're looking at
9:13
and show it to them in like just the SQL
9:15
terminal monitor and say one, two, three, boom, magic,
9:18
hit return on the SQL, database table changes,
9:21
all their maps immediately update. And that
9:23
was just the result of writing SQL. I didn't have to
9:25
like
9:25
deal with any sort of special
9:27
magic middleware piece. I
9:30
could just use SQL to do the updates. And
9:32
so it means that any client which can
9:35
talk directly to the post just tables can
9:37
participate in this live data. That's
9:39
kind of how I differentiate it. I've
9:41
gone way off base on your actual question, which is
9:43
unfortunate.
9:44
Now you're doing a great job.
9:46
But so I understand this like
9:49
this. So there's this functionality in the database called
9:51
listen notify, we can attach triggers to that.
9:53
So something happens in the database
9:56
and action takes place, we add something, we delete
9:58
something, we update something. I,
10:00
if I'm listening to this, this functionality,
10:03
I get a notification. This is great
10:05
if I am a
10:06
QJ's client, for example, that's connected directly
10:09
to the database. You've built this thing called
10:11
PGEventserve, which sits on
10:13
top of the database and adds the same functionality
10:16
to something called WebSockets, which
10:18
means a web client also
10:21
can be updated. You can force the update of
10:23
the map through this PGEventserve,
10:26
if I'm understanding you correctly. That's absolutely
10:28
correct. And even better, depending
10:30
on what your system is built for, even
10:32
better, the notification
10:34
can be a lot more precise
10:37
than just, hey, the table's changed. It
10:40
can be literally, hey, this object has
10:42
moved and here's its new coordinates. So
10:44
it's possible for the mapped up gain itself in a very granular
10:47
way.
10:47
It does not just have to go back and pull
10:49
the whole table again, redraw the whole thing. It
10:52
can, in fact, move objects one at a
10:54
time if the notification
10:56
is explicit about what's changed. Okay. So
10:59
what kind of clients will react to this? Like
11:02
what kind of clients have this functionality? You
11:04
might guess from the question that I am not a front-end
11:06
developer. But if I'm using something
11:08
like Leaflet, just as an example, well,
11:11
let's just work. There's going to be some
11:14
plumbing because there's not like an extant
11:16
standard that you can just say,
11:18
this is a moving object layer, go. You're
11:20
going to have to write a little bit of JavaScript
11:22
to connect to the WebSocket
11:25
and you're going to have to plumb between
11:28
the
11:28
events that are coming off that WebSocket and
11:30
your layer of things that are moving.
11:32
The good news is that the plumbing is really
11:35
quite small.
11:36
And also you can
11:38
subsume a lot of the complexity into the database
11:40
side because the listen
11:43
notify payload,
11:45
it's just a string. It's just a hunk of text.
11:48
So it's really quite easy to build a
11:50
JSON payload inside the database
11:53
and then fire that out through this piping.
11:55
So you end up with something which a little payload
11:57
is really quite web native. you
12:00
compose it in the database, it shows up in the
12:02
client, you can just say, oh, this is Jason, great, I'll parse
12:04
that and then act
12:06
based on it. You can see how narrow
12:09
the amount of code is by looking at the PGA events or
12:11
code base itself because it ships with a bunch
12:13
of examples, including live
12:15
examples of things that move. And you can see how small
12:18
or large
12:19
you can make the system inside the client.
12:22
But yeah, it does involve some JavaScript, it's not
12:24
point and shoot. One thing I
12:26
learned after publishing, I can't
12:29
remember what blog, some kind of blog post, someone
12:31
was nice enough to pipe up and say, hey, did
12:34
you know, I mean, you think this is really cool
12:36
and specific to like web tech, but in fact, you
12:38
just already does some of this. So
12:41
there are hiding in the barrels of
12:43
you just some facilities to
12:46
do
12:46
live response to listen notify as well,
12:49
which is really awesome. Because in all
12:52
my demonstrations, I just ended up showing having
12:55
to like manually force QGIS to redraw to
12:57
see that things have changed. Whereas in fact, you
12:59
can tell it, oh, watch for notifications and redraw
13:01
yourself, which is kind of mind blowing.
13:03
We also it means that all your clients can be completely
13:06
live.
13:06
That is really cool. Like if somebody's just been looking
13:08
like dragged in a bunch of data,
13:11
looking at it, and it's but it's changing in
13:13
real time or near real time, and they're doing
13:16
an analysis of that like, that's
13:18
great to be able to say, hey, you need to update this again.
13:20
How difficult is it to install
13:23
pg event serve? What does it take? It
13:25
takes almost nothing. pg event serve
13:27
is written in go, which ordinarily be like,
13:29
who cares?
13:30
But go is a surprisingly
13:33
multi platform language. And it also is
13:35
a language where it's very easy to
13:37
build completely self contained binaries.
13:40
So to
13:41
run pg event serve, you go to the pg
13:44
event serve page on GitHub,
13:46
or you just type pg underbar event serve in Google, and that'll
13:48
end up taking you there.
13:49
You can download builds for Linux
13:51
or Mac OS or Windows. And
13:54
inside those packages will be a single
13:56
executable,
13:57
but you just run you set an
13:59
environment variable to tell it.
13:59
which database connect to, and you run
14:02
it. That's it. If you're into containers,
14:05
there's also a container. I'm not. So
14:07
the idea of just running something sounds amazing.
14:09
What does it require in terms of the
14:12
data model? Do I need special time
14:14
stamps? Is
14:15
it looking for a specific field?
14:18
What's happening in there? Because the
14:21
Notify payload is just a Hadoa
14:23
text, there is no preset data
14:25
model.
14:26
It will take the Hadoa text that you generate in the
14:28
database and hand it to the web client
14:30
that's watching that channel. So it's
14:32
really contingent on you as the app designer to
14:35
format that Hadoa text in the way
14:37
that's most useful to your end client.
14:39
Almost always, that's going to end up being JSON,
14:41
but it could be anything you want. Given that
14:43
this is a geospatial podcast, this might be
14:46
the dumbest question ever, but is this
14:48
only for spatial events? No. In
14:51
fact, one of the demonstrations that ships
14:53
with it is like a little chat. You
14:55
can write your own Postgres chatbot. It
14:57
seems it's not, it doesn't seem it
15:00
is totally
15:00
pointless, but it does make not a bad
15:02
example. Okay. So
15:05
it sounds really cool. When I think about
15:07
use cases, I think about alerting
15:10
movement in and out of geofences
15:12
as an example, just the general, hey,
15:14
this thing has updated.
15:17
What else can you come up with in terms of use
15:19
cases just to help people start thinking
15:21
about what they could do with this? Well,
15:23
you kind of took them all away. Yeah. So
15:26
map update is one. I think it's probably actually less
15:30
interesting at scale than the
15:32
geofences. The nice thing about geofences
15:34
is again, you can program them entirely inside the database,
15:37
which is
15:38
great every time they end up being triggers inside
15:40
the database. Again, no third-party software required
15:43
to have a geolirting setup. The
15:46
real thing is any kind of thresholding.
15:48
So geofencing is a kind of thresholding.
15:51
It's just a spatial thresholding. This
15:53
thing has moved into the spatial area,
15:55
but it's a database. So we can work on
15:57
any kind of thresholding you want. An obvious way to do that
15:59
is to do that. one would be to set
16:02
limits on a measurement or have
16:04
a linear
16:05
model which is fitting to a
16:07
time series and throw an alert when
16:10
things become residuals outside
16:12
of an expected value range.
16:14
You can do an awful lot of statistical analysis right inside
16:16
of Postgres, either using PLR if
16:19
you're a complete statistical
16:22
super person.
16:23
Even if you're not a statistical super person, Postgres actually
16:25
ships with built
16:27
into it. It's just the standard functions. Linear
16:30
regression. You can do least squares
16:32
analysis right inside your database and
16:34
get analyses of the residuals.
16:37
You can look and say, okay, the latest value is outside
16:39
of my expected value
16:41
based on the last three hours. Therefore, I'm going to
16:43
throw up an event and something will happen. That is really cool.
16:45
Can you maybe
16:47
give us a little bit of an understanding of how flexible those triggers
16:50
can be? Can
16:52
I use something like this to look at changes
16:54
over time?
16:55
Can I aggregate changes and say, look, this
16:57
has been the net movement over an hour
17:00
or something like that? Yes. I
17:03
mean, the triggers themselves are like
17:04
three lines of code. All they say is, for a
17:07
given event and a database, there's
17:09
really only like four, three, four.
17:11
Anyways, insert, update, delete, three.
17:14
For a given event, run this function.
17:17
And that's where it gets incredibly huge because
17:20
this function
17:21
can be of any length
17:24
and call any number of SQL commands
17:26
can have whole bunch of the places where it maintains
17:29
its state internally. Like it's not just one SQL
17:31
call. It's as many as you want to write. There
17:33
is a default language PLPG SQL.
17:35
You can write functions in, but you can also write them in
17:38
third party languages. You can write
17:40
your functions in Python and take
17:42
advantage of any Python module that
17:44
happens to be inside your runtime.
17:46
So you can in fact do like machine
17:48
learning stuff inside your functions.
17:51
Wow. Like anything you can program,
17:54
you can attach to a trigger and have run
17:56
when an event occurs inside the database. Anything.
18:01
Wow. Okay. So I'm sure there's a bunch
18:03
of people that are much more skilled at this than I
18:05
am, that have way better ideas
18:07
than I do. So I'm going to let them figure it out
18:09
from here in terms of what's possible. I want
18:11
to sort of jump back into this idea of
18:14
real-time updates or synchronous
18:16
data maybe. Could you tell us what
18:19
were people doing before and what does
18:21
this replace? So you mentioned this idea of polling
18:23
before. I think we're all pretty used to
18:26
the idea of, you know, we pan the map, you know,
18:28
we stream data in. When is this
18:30
the right answer? And when is this alerting
18:32
the right answer? If you had to draw a bit of a line
18:34
in the sand? I would say alerting is the
18:37
right answer when it really
18:39
is a real-time problem
18:42
because you can get a long way
18:43
with polling and it's not like
18:46
five minute old data
18:48
is bad. It's like most of the time five minute old
18:50
data is like incredibly good and
18:52
far better than anyone ever expected before.
18:54
There's a
18:55
fetishism around true
18:57
real-timeness, which I admit
19:00
the pandering to with this tool
19:02
set. You can get a long way with just polling.
19:04
You still probably maybe should think about having
19:07
events come live off your database
19:09
because it's such a lovely
19:11
system that ties
19:13
in
19:13
computation with model state
19:16
and taking as much advantage of it as you can
19:18
before you start building external model state
19:21
is really a good idea just from like a programming
19:23
efficiency point of view. There's
19:24
this weird bifurcation
19:27
between when is real-time
19:29
needed and when it is not. And you can kind
19:31
of see it in like things like the Uber app or
19:33
really anything where you've got like a moving car
19:36
or something,
19:37
where like most time people's
19:39
expectation and requirement for real-time data
19:41
is way lower than they think. It's like, yeah,
19:43
yeah, real-time. We want that to be real-time.
19:45
Definitely deliver that.
19:46
And then the reality is you give them five minute data
19:48
and it's not going to change their decision
19:51
process to have two second data. And
19:53
yet things flip over when you start to look
19:57
at things like
19:58
cars moving on phones.
19:59
where all of a sudden, not only do
20:02
you want to have this illusion of seeing
20:04
exactly where the vehicle is, the actual
20:06
data the vehicle is producing, like the
20:08
GPS stream is less accurate
20:12
than the user expects it to be.
20:15
Because GPS tracks are like
20:17
plus or minus five meters and the data
20:19
is literally only coming in from the vehicle every 30
20:22
seconds. And yet people want to see
20:24
the vehicle kind of smoothly transition
20:26
along the road network and turn left
20:28
at the corner. Whereas if you just do the GPS
20:31
track, the vehicle will be
20:32
hopping across blocks and driving through houses.
20:34
There's a strange requirement at
20:36
the visualization level where people just
20:39
end up going deeper and deeper and deeper to the point where at
20:41
some point they actually want to look at data which
20:43
doesn't exist. They want to look at things that are
20:46
higher resolution than
20:47
the most real-time data they can
20:49
get at.
20:50
So it's a
20:52
push and pull, I think, between the people who are consuming
20:54
the real-time data
20:56
and the people who are actually working
20:58
with it. I realize, of course, at the end of
21:00
the day is the people that are building
21:02
these systems on top of tools like this that make
21:04
the decisions, they decide what's important to them. But
21:06
I really appreciate your perspective
21:08
there. And I love that example of the
21:11
GPS locations of cars. I think this is great.
21:13
In that example, at least in my mind, real-time
21:16
is not an advantage. I would rather have a smooth
21:19
transition, I think you call it, as
21:21
opposed to cars jumping in and
21:23
out of different lanes and through houses
21:26
and moving around in real-time.
21:28
That's not helpful. I think something
21:31
at a lower resolution would be much
21:33
more helpful.
21:34
My last question here for you, or one of my
21:36
last questions is, is this a cool hobby
21:38
project or is this... Could I
21:40
take this today and use it in a production environment?
21:43
You could.
21:44
It's a wonderfully small project. It
21:46
is the most useful tiny thing
21:48
I think I've ever written. So I haven't seen
21:51
any breakages on it from users.
21:54
I've shoved it through very high load
21:56
testing and it found some places where it made mistakes
21:58
and got rid of them. And now it doesn't break.
21:59
break, and what it provides is so
22:02
narrow and simple.
22:03
The main thing where people might not be using it in production
22:06
is it does depend on being
22:08
able to maintain the state of your system inside
22:10
the database model. And it is possible in geospatial
22:12
world
22:13
to have a large enough corpus
22:16
of continuously moving things that maintaining
22:18
the model state inside the database
22:21
is actually just like
22:22
too much transactional churn for the database.
22:24
You have 10,000
22:26
all simultaneously moving objects, spitting
22:29
back changes every five seconds. That's
22:32
a large number of transactions per second.
22:34
And you might begin to the point where the database isn't the best
22:37
place to have that model
22:39
running quickly if you're asking questions of it,
22:41
like fire off alerts when things get close
22:43
to each other. But for
22:45
lots and lots and lots of practical purposes, it seems
22:48
like, yeah, put into production. It's
22:50
simple. It doesn't break. I
22:52
hear far more complaints about my tile service
22:55
than I do about this thing.
22:57
Well,
23:00
I guess that's a really good sign that you hear more
23:02
complaints about your other pieces of work
23:04
than you do about this one. Which
23:08
I should bracket by saying it, the tile service
23:10
is like four years older
23:14
and mostly asked questions of the database. It's just,
23:16
I don't know, it has to do with
23:19
the underlying complexity of what you want the system
23:21
to do. And if it's a very, very small
23:23
tool, which do very constrained things,
23:26
you can kind of reason about
23:27
and feel confident about in ways
23:29
that you can't with systems that have
23:32
fewer constraints. So the tile service is
23:34
a more complex system. So it's
23:36
not as perfect as the event server is.
23:39
Well, I'm sure if you built it, I'm sure it's
23:41
good enough, if nothing else. Where
23:43
can people go if they want to check this out?
23:46
If you type PG Underbar Event Serve into Google,
23:48
you will find the GitHub page, which
23:51
has a lovely explanatory text
23:53
right up front, which will tell you what you can download.
23:56
Again, it's the binary to the download.
23:57
The documentation explains how to set
23:59
it up. how to run the examples,
24:01
you should be able to get something up and
24:03
running real, real fast. The main
24:05
sort of prerequisite is, you know, it's web
24:08
tech, so you've got to know enough about web tech
24:10
to write your own web map. So this
24:12
is where we can find the tool that you've built, pgeventserv.
24:15
There'll be people listening to this that would
24:17
like to reach out to you, hear more from you.
24:20
Where could they go to do that? If you go to cleverelephant.ca,
24:23
that's my contact information and also
24:25
blogs I publish about a number of topics
24:27
including this kind of stuff.
24:28
I also work for Crunchy Data Solutions,
24:31
which is a Postgres support company.
24:33
They have a blog. A lot of my content
24:35
on things like eventserv and tileserv
24:37
and other things you can do with PostGIS
24:39
resides there. So if you go to the Crunchy Data
24:41
blog and type in my name as the author,
24:43
you'll see some pretty cool talks. Oh,
24:46
the other one which is great is PostGIS
24:48
Day. We've had four
24:51
of them
24:51
now, online PostGIS Day,
24:54
and all the videos
24:56
are published online on
24:58
YouTube. So if you go to the Crunchy Data video channel, you
25:00
can find the PostGIS Day talks, including for
25:02
this last year, a specific talk on
25:04
pgeventserv, which might be the best entry point
25:06
to the topic. I'm really pleased you mentioned
25:08
that. I've actually watched that on YouTube myself and it was
25:11
brilliant. I will definitely include a link to
25:13
that in the show notes. Right, Paul, thank
25:15
you very much. Thanks for showing up
25:17
again, giving us your time and teaching
25:20
us a lot as well about the tool
25:22
that you've built and
25:23
about PostGIS, GIS in general.
25:26
I really appreciate it. Yeah, cheers.
25:28
Thanks for having me.
25:31
Thank you very much for listening all the way to the end. I really
25:33
hope you enjoyed that episode with Paul about
25:35
pgeventserv. As always,
25:37
there'll be links in the show notes. Check them out.
25:40
I'll link to the pgeventserv on GitHub and
25:43
of course, the demonstration of pgeventserv
25:46
in action on YouTube. And
25:49
as I mentioned in the introduction, Paul has been
25:51
on the podcast a bunch of times before. So
25:53
if you want to hear more from him, which
25:56
would be a great idea, there'll be links
25:58
to those episodes in the show notes of.
25:59
this episode. If you want to reach out to me
26:02
for whatever reason, you'll find contact information
26:04
at mapscaping.com. I'd love to hear from
26:06
you. Ok, that's it for me. See you again
26:08
next week. Bye.
Podchaser is the ultimate destination for podcast data, search, and discovery. Learn More