Skip to content

Improve Overpass query - #336

Open
7h30n3 wants to merge 1 commit into
masterfrom
seq_overpass
Open

Improve Overpass query#336
7h30n3 wants to merge 1 commit into
masterfrom
seq_overpass

Conversation

@7h30n3

@7h30n3 7h30n3 commented Jul 1, 2026

Copy link
Copy Markdown
Member

This PR will hopefully make the Overpass query for stop areas more reliable.
It adresses the following things:

Change from GET to POST

According to this best practice:

Prefer POST requests over GET requests where possible.

Set Timeout in Seconds

Up until now the timeout was send in milliseconds and ccording to the language reference:

[...] the higher this value, the more probably the server rejects the query before executing it.

Round Robin

The PR introduces a sequential querying with one query for a server at a time. Only if the server responded the next query is sent.

Additional Server

An additional Overpass Server was added to better distribute the load.

- Change from GET to POST
- Set Timeout in Seconds
- Implement sequential querying with one query for a server at a time
@7h30n3
7h30n3 requested a review from Robbendebiene July 1, 2026 10:01
final _random = Random();
int _currentServerIndex = 0;

final Map<String, Completer<void>> _serverLocks = {};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not also work with the index / via List here? final List<Completer<void>>

Comment on lines 30 to +32
'https://overpass-api.de/api/interpreter',
'https://maps.mail.ru/osm/tools/overpass/api/interpreter',
'https://overpass.private.coffee/api/interpreter',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last time we checked private coffee was way more responsive than the main overpass server. This is why I would only include it for now (even though it reduces the usefulness of the round robin implementation).

Comment on lines +43 to +46
for (final server in apiServers) {
_serverLocks[server] = Completer<void>()..complete();
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use _serverLocks = List.filled(3, Completer<void>()..complete(), gorwable = false); or List.generate directly inside the constructor assignment.

_currentServerIndex = (_currentServerIndex + 1) % apiServers.length;

// Wait for the server to be free
await _serverLocks[url]!.future;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't it be the case that:

  • _currentServerIndex = 1
  • server at index 0 and 1 are already done
  • server at index 2 is still busy
    -> we wait even though there are free servers?

Also if _query is called rapidly from the outside (e.g. called 4 times when we have 3 servers) then 2 of these queries will wait on the same completer/future to be finished and once it is finished one will override the lock of the other and both server requests will be run.

I think I prefer a queue based approach where all query tasks are queued inside a Queue and once a query finishes it checks whether something is still in the queue. If it finds something it takes it (removes it from the queue) and runs another query.

Also I think we could improve the retry functionality. I suspect that some requests get blocked by the server with "too many requests" or something similar, in this case retrying the query just makes everything worse.

Comment on lines +98 to +99
// Release lock before waiting for retry to allow other cells to use this server slot during delay
_serverLocks[url]!.complete();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be necessary as return is immediately called (there is no await) wherefore the finally block will run afterwards. For clarification: finally always runs even if the function already returns. It will run after the return.

Also I wonder whether a completer is really necessary. We might just be able to store the Future (or a wrapped version of it) from the _dio.post directly inside _serverLocks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants