简体   繁体   English

通过 Rails 查询 PostGIS 时出现间歇性错误(字符串插值失败?)

[英]Intermittent error in PostGIS query via Rails (string interpolation failure?)

I have an intermittent error come up after some deploys of my Rails app.在部署我的 Rails 应用程序后出现间歇性错误。

This code is running in Sidekiq (5 processes each with 10 threads), which is running in a Docker container.此代码在 Sidekiq 中运行(5 个进程,每个进程有 10 个线程),它在 Docker 容器中运行。 I can have tens of thousands of these jobs queued up at any point.我可以在任何时候让数以万计的这些工作排队。

path = Path.find(path_id)
nearby_nodes = Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog.to_s)

The error is:错误是:

ActiveRecord::StatementInvalid: PG::InternalError: ERROR: parse error - invalid geometry
HINT: "01" <-- parse error at position 2 within geometry
PG::InternalError: ERROR: parse error - invalid geometry
HINT: "01" <-- parse error at position 2 within geometry

I can get these jobs to run successfully if I quiet all the Sidekiq processes, stop the workers, wait a moment, then start the workers back up.如果我让所有 Sidekiq 进程安静下来,停止工作人员,稍等片刻,然后重新启动工作人员,我可以让这些工作成功运行。

I added a number of delays to my deploy process (guessing that slowing things down might help, if restarting workers solves the problem), but that did not help.我在部署过程中添加了一些延迟(如果重新启动工作人员可以解决问题,我猜测放慢速度可能会有所帮助),但这并没有帮助。

I can usually get one successful deploy per day.我通常每天可以成功部署一次。 After that first deploy, it's more likely to fall into this failure state & if it gets into this state every deploy thereafter will cause this same issue.在第一次部署之后,它更有可能陷入此故障 state 并且如果它进入此 state 之后的每次部署都会导致同样的问题。

Path.first.geog returns: #<RGeo::Geographic::SphericalPointImpl:0x3ffd8b2a6688 "POINT (-72.633932 42.206081)"> Path.first.geog返回: #<RGeo::Geographic::SphericalPointImpl:0x3ffd8b2a6688 "POINT (-72.633932 42.206081)">

Path.first.geog.class returns: RGeo::Geographic::SphericalPointImpl Path.first.geog.class返回: RGeo::Geographic::SphericalPointImpl

I've tried a number of different formats of this query, which might shed some light on how/why this is failing (though I'm still stumped as to why it's only intermittent):我已经尝试了许多不同格式的这个查询,这可能会揭示它是如何/为什么失败的(尽管我仍然对为什么它只是间歇性的感到困惑):

  1. Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog) fails, generating this query: Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog)失败,生成此查询:
Node Load (1.0ms)  SELECT "nodes".* FROM "nodes" WHERE (ST_DWITHIN(geog, ST_GeographyFromText('0020000001000010e6c05228925785f8d340451a60dcb9a9da'), 25)) LIMIT $1  [["LIMIT", 11]]

and this error:这个错误:

ActiveRecord::StatementInvalid (PG::InternalError: ERROR:  parse error - invalid geometry)
HINT:  "00" <-- parse error at position 2 within geometry
  1. Node.where("ST_DWITHIN(geog, ST_GeographyFromText('#{path.geog}'), 25)") succeeds, generating this query: Node.where("ST_DWITHIN(geog, ST_GeographyFromText('#{path.geog}'), 25)")成功,生成以下查询:
Node Load (5.1ms)  SELECT "nodes".* FROM "nodes" WHERE (ST_DWITHIN(geog, ST_GeographyFromText('POINT (-72.633932 42.206081)'), 25)) LIMIT $1  [["LIMIT", 11]]
  1. Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog.to_s) also succeeds, generating the same query: Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog.to_s)也成功,生成相同的查询:
Node Load (2.3ms)  SELECT "nodes".* FROM "nodes" WHERE (ST_DWITHIN(geog, ST_GeographyFromText('POINT (-72.633932 42.206081)'), 25)) LIMIT $1  [["LIMIT", 11]]
  1. Doing the to_s conversion in a preceding line as some kind of superstitious test also works:在前一行中进行to_s转换作为某种迷信测试也有效:
geog_string  = path.geog.to_s
nearby_nodes = Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", geog_string)

Queries 2-4 generally work, but behave like query number 1 some of the time and only after a deploy .查询 2-4 通常可以工作,但有时表现得像查询 1 并且仅在 deploy 之后 I could not make 2-4 behave like the first query in a Rails console.我无法让 2-4 表现得像 Rails 控制台中的第一个查询。 The only time queries 2-4 behave like the first query is in a Sidekiq job after a deploy.唯一一次查询 2-4 表现得像第一个查询是在部署后的 Sidekiq 作业中。 It's as if the string conversion isn't working sometimes.好像字符串转换有时不起作用。

Here's a list of potentially relevant gems/versions:以下是可能相关的 gem/版本的列表:

  • activerecord-postgis-adapter (6.0.0) activerecord-postgis-适配器 (6.0.0)
  • pg (1.2.3) pg (1.2.3)
  • rails (6.0.2.2)导轨 (6.0.2.2)
  • rgeo (2.1.1) rgeo (2.1.1)
  • rgeo-activerecord (6.2.1) rgeo-activerecord (6.2.1)
  • sidekiq (6.0.6) sidekiq (6.0.6)
  • Ruby 2.6.6 Ruby 2.6.6
  • PostgreSQL 11.6 PostgreSQL 11.6
  • PostGIS 2.5.2地理信息系统 2.5.2
  • Docker 19.03.8, build afacb8b7f0 Docker 19.03.8,构建 afacb8b7f0

There is no need to convert the geography to a string, and then to read it back as a geography.无需将地理转换为字符串,然后将其作为地理读回。

You can try directly可以直接试试

Node.where("ST_DWITHIN(geog, ?, 25)", path.geog)

That being said, you may indeed have some invalid geometries话虽如此,您可能确实有一些无效的几何图形

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM