@@ -21,7 +21,7 @@ We must make sure that the application works properly in these states.
...
@@ -21,7 +21,7 @@ We must make sure that the application works properly in these states.
For GitLab.com, we also run a set of canary servers which run a more recent version of the application. Users with
For GitLab.com, we also run a set of canary servers which run a more recent version of the application. Users with
the canary cookie set would be handled by these servers. Some URL patterns may also be forced to the canary servers,
the canary cookie set would be handled by these servers. Some URL patterns may also be forced to the canary servers,
even without the cookie being set. This also means that some pages may match the pattern and get handled by canary servers,
even without the cookie being set. This also means that some pages may match the pattern and get handled by canary servers,
but AJAX requests to URLs (like the GraphQL endpoint) won't match the pattern.
but AJAX requests to URLs (like the GraphQL endpoint) fail to match the pattern.
With this canary setup, we'd be in this mixed-versions state for an extended period of time until canary is promoted to
With this canary setup, we'd be in this mixed-versions state for an extended period of time until canary is promoted to
production and post-deployment migrations run.
production and post-deployment migrations run.
...
@@ -38,7 +38,7 @@ default. The feature flag can be enabled when the deployment is in a
...
@@ -38,7 +38,7 @@ default. The feature flag can be enabled when the deployment is in a
consistent state. However, this method of synchronization doesn't
consistent state. However, this method of synchronization doesn't
guarantee that customers with on-premise instances can [upgrade with
guarantee that customers with on-premise instances can [upgrade with
zero downtime](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates)
zero downtime](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates)
since point releases bundle many changes together. Minimizing the time
because point releases bundle many changes together. Minimizing the time
between when versions are out of sync across the fleet may help mitigate
between when versions are out of sync across the fleet may help mitigate
errors caused by upgrades.
errors caused by upgrades.
...
@@ -70,7 +70,7 @@ This type of change may look like an immediate switch between the two implementa
...
@@ -70,7 +70,7 @@ This type of change may look like an immediate switch between the two implementa
especially with the canary stage, there is an extended period of time where both version of the code
especially with the canary stage, there is an extended period of time where both version of the code
coexists in production.
coexists in production.
1.**expand**: a new route is added, pointing to the same controller as the old one. But nothing in the application will generate links for the new routes.
1.**expand**: a new route is added, pointing to the same controller as the old one. But nothing in the application generates links for the new routes.
1.**migrate**: now that every machine in the fleet can understand the new route, we can generate links with the new routing.
1.**migrate**: now that every machine in the fleet can understand the new route, we can generate links with the new routing.
1.**contract**: the old route can be safely removed. (If the old route was likely to be widely shared, like the link to a repository file, we might want to add redirects and keep the old route for a longer period.)
1.**contract**: the old route can be safely removed. (If the old route was likely to be widely shared, like the link to a repository file, we might want to add redirects and keep the old route for a longer period.)
...
@@ -84,7 +84,7 @@ When we need to add a new parameter to a Sidekiq worker class, we can split this
...
@@ -84,7 +84,7 @@ When we need to add a new parameter to a Sidekiq worker class, we can split this
1.**migrate**: we add the new parameter to all the invocations of the worker.
1.**migrate**: we add the new parameter to all the invocations of the worker.
1.**contract**: we remove the default value.
1.**contract**: we remove the default value.
At a first look, it may seem safe to bundle expand and migrate into a single milestone, but this will cause an outage if Puma restarts before Sidekiq.
At a first look, it may seem safe to bundle expand and migrate into a single milestone, but this causes an outage if Puma restarts before Sidekiq.
Puma enqueues jobs with an extra parameter that the old Sidekiq cannot handle.
Puma enqueues jobs with an extra parameter that the old Sidekiq cannot handle.
### Database migrations
### Database migrations
...
@@ -134,12 +134,12 @@ And these deployments align perfectly with application changes.
...
@@ -134,12 +134,12 @@ And these deployments align perfectly with application changes.
With all those details in mind, let's imagine we need to replace a query, and this query has an index to support it.
With all those details in mind, let's imagine we need to replace a query, and this query has an index to support it.
1.**expand**: this is the from `Schema A` to `Schema B` deployment. We add the new index, but the application will ignore it for now
1.**expand**: this is the from `Schema A` to `Schema B` deployment. We add the new index, but the application ignores it for now.
1.**migrate**: this is the `Version N` to `Version N+1` application deployment. The new code is deployed, at this point in time only the new query will run.
1.**migrate**: this is the `Version N` to `Version N+1` application deployment. The new code is deployed, at this point in time only the new query runs.
1.**contract**: from `Schema B` to `Schema C` (post-deployment migration). Nothing uses the old index anymore, we can safely remove it.
1.**contract**: from `Schema B` to `Schema C` (post-deployment migration). Nothing uses the old index anymore, we can safely remove it.
This is only an example. More complex migrations, especially when background migrations are needed will
This is only an example. More complex migrations, especially when background migrations are needed may
still require more than one milestone. For details please refer to our [migration style guide](migration_style_guide.md).
require more than one milestone. For details please refer to our [migration style guide](migration_style_guide.md).
@@ -30,7 +30,7 @@ In some cases the query count might change slightly between runs for unrelated r
...
@@ -30,7 +30,7 @@ In some cases the query count might change slightly between runs for unrelated r
## Cached queries
## Cached queries
By default, QueryRecorder will ignore[cached queries](merge_request_performance_guidelines.md#cached-queries) in the count. However, it may be better to count
By default, QueryRecorder ignores[cached queries](merge_request_performance_guidelines.md#cached-queries) in the count. However, it may be better to count
all queries to avoid introducing an N+1 query that may be masked by the statement cache.
all queries to avoid introducing an N+1 query that may be masked by the statement cache.
To do this, this requires the `:use_sql_query_cache` flag to be set.
To do this, this requires the `:use_sql_query_cache` flag to be set.
You should pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
You should pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
...
@@ -73,7 +73,7 @@ There are multiple ways to find the source of queries.
...
@@ -73,7 +73,7 @@ There are multiple ways to find the source of queries.
- View the call backtrace for the specific `QueryRecorder` instance you want
- View the call backtrace for the specific `QueryRecorder` instance you want
by using `ActiveRecord::QueryRecorder.new(query_recorder_debug: true)`. The output
by using `ActiveRecord::QueryRecorder.new(query_recorder_debug: true)`. The output
will be in `test.log`
is stored in file `test.log`.
- Enable the call backtrace for all tests using the `QUERY_RECORDER_DEBUG` environment variable.
- Enable the call backtrace for all tests using the `QUERY_RECORDER_DEBUG` environment variable.
...
@@ -83,7 +83,7 @@ There are multiple ways to find the source of queries.
...
@@ -83,7 +83,7 @@ There are multiple ways to find the source of queries.