-
Notifications
You must be signed in to change notification settings - Fork 3
Conversation
end | ||
raise InvalidIncrementException unless valid_steps | ||
end | ||
|
||
def self.get_uid_for_class(klass, options = {}) | ||
with_connections do |connection| | ||
Timeout.timeout(self.global_uid_options[:query_timeout], TimeoutException) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate issue that we should come back for later: Timeout.timeout
is bad mojo and we should do the query timeout some other way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ggrossman perhaps we should have the alloc server connections set the wait_timeout
MySQL session variable to the configured self.global_uid_options[:query_timeout]
That will remove the need for us to manage a timeout here, and the bad mojo that comes with it.
E.g. in the database.yml
test_id_server_1:
<<: *MYSQL
database: global_uid_test_id_server_1
variables:
auto_increment_increment: 5
auto_increment_offset: 1
max_execution_time: 10
test_id_server_2:
<<: *MYSQL
database: global_uid_test_id_server_2
variables:
auto_increment_increment: 5
auto_increment_offset: 2
max_execution_time: 10
That avoids the need for this gem to mess around with connection variables too, giving the client complete control.
EDIT: Ah, nvm. max_execution_time
is only supported in MySQL 5.7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea. I'm in favor of that. We should document that the alloc server connections should definitely declare an appropriate wait_timeout
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could wait for another PR but it's a good idea to get rid of Timeout.timeout
. It can cause entirely unpredictable badness if it actually triggers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback @ggrossman! I pushed the draft PR up early for visibility, sorry, I should have been more clear that it was a still a work in progress and I intended to make more changes :)
6a44c31
to
6915462
Compare
I wonder if we should make separate PRs of each of the three “remove” commits:
|
1455d1f
to
862e9b1
Compare
213e7d7
to
c2480db
Compare
I forgot to mention that this work along with the work below is targeted for a 4.0.0 gem release (milestone) since the gem is undergoing significant change.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So many comments. Sorry.
beacf78
to
5f90b12
Compare
Addressed feedback, squashed and force pushed, thanks for the solid review 🙏 |
I'll leave it open for another 48 hours in case others want to provide feedback before merging. |
e9e929a
to
184a8f3
Compare
184a8f3
to
b68ec42
Compare
b68ec42
to
4b3bdbc
Compare
Addressed feedback, squashed and force pushed. Thanks |
[Breaking change] This patch adds `auto_increment_increment` validation to the following scenarios: * Connection initalization * Generating one ID * Generating multiple IDs These changes should have no noticeable impact on performance and are thread safe. The intent is to prevent data corruption when a server is misconfigured and in the event that one is found, it's removed from the pool of available alloc servers allowing creation to continue with the valid alloc servers. Validation during initialization is done by comparing the client configuration and with what's set on each server. If the server is misconfigured, an error is reported via the `notifier` and it's left out of the pool. Validation during creation happens by comparing each pair of identifiers and ensuring they've been incremented correctly by the configured amount. If the `auto_increment_increment` changes while the clients are using the server, the alloc server is removed from the list of servers and an error is reported via the `notifier`. An InvalidIncrementException is raised if all servers are misconfigured. The changeset is considered a breaking change as any clients upgrading will see an increment exception if their `increment_by` was set incorrectly, this previously would have gone unnoticed.
4b3bdbc
to
eb5fd15
Compare
Updated the commit message to reflect the final state |
This patch adds
auto_increment_increment
validation to the following scenarios:A lot of refactoring was done as part of this PR and has either been merged separately or moved to #70
These changes have been benchmarked, should have no noticeable impact to performance and continue to be thread safe.
Validation during initialization is done by comparing the client configuration (
increment_by
) with each alloc server (auto_increment_increment
). If the server is misconfigured, an error is reported via thenotifier
(defaults to error logs) and it's removed from the pool. The connection will be retried every 10 minutes (configurable via theconnection_retry
) indefinitely.Validation during allocation happens by storing the ID returned and comparing it with the last 4 identifiers, ensuring they've been incremented correctly by the configured amount. The alloc servers are shared and there's no guarantee that the process will get the next increment. As an example, one process (think unicorn worker or puma thread) may receive 5, 15, 25 while the other received 10 & 20. This is why we validate by checking the remained. This will not raise an error if the
auto_increment_increment
increases by a factor of 2.If the
auto_increment_increment
changes while the clients are using the server, the alloc server is removed from the list of servers and an error is reported via thenotifier
. The server is retried after a minute, indefinitely.An exception is raised and ID allocation ceases if all servers are misconfigured. This will result in the process raising a
NoServersAvailableException
exception and halting. New unicorns or puma threads will attempt to connect each time they are spawned.To support valid updates to the
auto_increment_increment
on active alloc servers, thesuppress_increment_exceptions
option can be used to swallow the exceptions and call the notifier. This will allow those who have monitors configured to be notified of the change and also allow the servers to remain in use while the update is being performed.Related: