通过 Rails 在 PostGIS 查询中出现间歇性错误(字符串插值失败?)
Intermittent error in PostGIS query via Rails (string interpolation failure?)
我在 一些 部署我的 Rails 应用程序后出现间歇性错误。
此代码在 Sidekiq 中 运行ning(5 个进程,每个进程有 10 个线程),运行ning 在 Docker 容器中。
我可以随时让数以万计的这些工作排队。
path = Path.find(path_id)
nearby_nodes = Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog.to_s)
错误是:
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
如果我让所有 Sidekiq 进程安静下来,停止 worker,稍等片刻,然后重新启动 worker,我就可以成功地将这些作业 运行。
我在我的部署过程中添加了一些延迟(猜测放慢速度可能会有所帮助,如果重新启动工作人员可以解决问题),但这没有帮助。
我通常每天都能成功部署一次。在第一次部署之后,它更有可能陷入这种失败状态,如果它进入这种状态,此后的每次部署都会导致同样的问题。
Path.first.geog
returns:
#<RGeo::Geographic::SphericalPointImpl:0x3ffd8b2a6688 "POINT (-72.633932 42.206081)">
Path.first.geog.class
returns:
RGeo::Geographic::SphericalPointImpl
我已经尝试了多种不同的查询格式,这可能会阐明 how/why 这是失败的(尽管我仍然不知道为什么它只是间歇性的):
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 [["LIMIT", 11]]
和这个错误:
ActiveRecord::StatementInvalid (PG::InternalError: ERROR: parse error - invalid geometry)
HINT: "00" <-- parse error at position 2 within geometry
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 [["LIMIT", 11]]
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 [["LIMIT", 11]]
- 在前一行中进行
to_s
转换作为某种迷信测试也有效:
geog_string = path.geog.to_s
nearby_nodes = Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", geog_string)
查询 2-4 通常有效,但表现得像查询编号 1 有时 和 仅在部署后 。
我无法使 2-4 的行为类似于 Rails 控制台中的第一个查询。
唯一一次查询 2-4 表现得像第一个查询是在部署后的 Sidekiq 作业中。
好像有时字符串转换不起作用。
这是一个可能相关的列表 gems/versions:
- activerecord-postgis-adapter (6.0.0)
- pg (1.2.3)
- rails (6.0.2.2)
- rgeo (2.1.1)
- rgeo-activerecord (6.2.1)
- sidekiq (6.0.6)
- Ruby 2.6.6
- PostgreSQL 11.6
- PostGIS 2.5.2
- Docker 19.03.8,构建 afacb8b7f0
无需将地理信息转换为字符串,然后再将其作为地理信息读回。
你可以直接试试
Node.where("ST_DWITHIN(geog, ?, 25)", path.geog)
话虽如此,您可能确实有一些无效的几何形状
我在 一些 部署我的 Rails 应用程序后出现间歇性错误。
此代码在 Sidekiq 中 运行ning(5 个进程,每个进程有 10 个线程),运行ning 在 Docker 容器中。 我可以随时让数以万计的这些工作排队。
path = Path.find(path_id)
nearby_nodes = Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", path.geog.to_s)
错误是:
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
如果我让所有 Sidekiq 进程安静下来,停止 worker,稍等片刻,然后重新启动 worker,我就可以成功地将这些作业 运行。
我在我的部署过程中添加了一些延迟(猜测放慢速度可能会有所帮助,如果重新启动工作人员可以解决问题),但这没有帮助。
我通常每天都能成功部署一次。在第一次部署之后,它更有可能陷入这种失败状态,如果它进入这种状态,此后的每次部署都会导致同样的问题。
Path.first.geog
returns:
#<RGeo::Geographic::SphericalPointImpl:0x3ffd8b2a6688 "POINT (-72.633932 42.206081)">
Path.first.geog.class
returns:
RGeo::Geographic::SphericalPointImpl
我已经尝试了多种不同的查询格式,这可能会阐明 how/why 这是失败的(尽管我仍然不知道为什么它只是间歇性的):
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 [["LIMIT", 11]]
和这个错误:
ActiveRecord::StatementInvalid (PG::InternalError: ERROR: parse error - invalid geometry)
HINT: "00" <-- parse error at position 2 within geometry
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 [["LIMIT", 11]]
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 [["LIMIT", 11]]
- 在前一行中进行
to_s
转换作为某种迷信测试也有效:
geog_string = path.geog.to_s
nearby_nodes = Node.where("ST_DWITHIN(geog, ST_GeographyFromText(?), 25)", geog_string)
查询 2-4 通常有效,但表现得像查询编号 1 有时 和 仅在部署后 。 我无法使 2-4 的行为类似于 Rails 控制台中的第一个查询。 唯一一次查询 2-4 表现得像第一个查询是在部署后的 Sidekiq 作业中。 好像有时字符串转换不起作用。
这是一个可能相关的列表 gems/versions:
- activerecord-postgis-adapter (6.0.0)
- pg (1.2.3)
- rails (6.0.2.2)
- rgeo (2.1.1)
- rgeo-activerecord (6.2.1)
- sidekiq (6.0.6)
- Ruby 2.6.6
- PostgreSQL 11.6
- PostGIS 2.5.2
- Docker 19.03.8,构建 afacb8b7f0
无需将地理信息转换为字符串,然后再将其作为地理信息读回。
你可以直接试试
Node.where("ST_DWITHIN(geog, ?, 25)", path.geog)
话虽如此,您可能确实有一些无效的几何形状