Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1b8bee4713
commit
64879e0d25
|
|
@ -1 +1 @@
|
|||
eb76930d3eed5e5faac7155d2d403aa69ff3baa2
|
||||
f83abd051b37dee24d683ca73db736f392e183e6
|
||||
|
|
|
|||
|
|
@ -14,27 +14,4 @@ class Dashboard::TodosController < Dashboard::ApplicationController
|
|||
|
||||
push_frontend_feature_flag(:todos_bulk_actions, current_user)
|
||||
end
|
||||
|
||||
def destroy
|
||||
todo = current_user.todos.find(params[:id])
|
||||
|
||||
TodoService.new.resolve_todo(todo, current_user, resolved_by_action: :mark_done)
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
redirect_to dashboard_todos_path, status: :found, notice: _('To-do item successfully marked as done.')
|
||||
end
|
||||
format.js { head :ok }
|
||||
format.json { render json: todos_counts }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def todos_counts
|
||||
{
|
||||
count: current_user.todos_pending_count,
|
||||
done_count: current_user.todos_done_count
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ class Namespace < ApplicationRecord
|
|||
delegate :math_rendering_limits_enabled?,
|
||||
:lock_math_rendering_limits_enabled?,
|
||||
to: :namespace_settings
|
||||
delegate :add_creator, :pending_delete, :pending_delete=, :deleted_at, :deleted_at=,
|
||||
delegate :add_creator, :deleted_at, :deleted_at=,
|
||||
to: :namespace_details
|
||||
delegate :resource_access_token_notify_inherited,
|
||||
:resource_access_token_notify_inherited=,
|
||||
|
|
|
|||
|
|
@ -264,19 +264,12 @@ class Todo < ApplicationRecord
|
|||
distinct.pluck(:user_id)
|
||||
end
|
||||
|
||||
# Count todos grouped by user_id and state, using an UNION query
|
||||
# so we can utilize the partial indexes for each state.
|
||||
def count_grouped_by_user_id_and_state
|
||||
grouped_count = select(:user_id, 'count(id) AS count').group(:user_id)
|
||||
|
||||
done = grouped_count.where(state: :done).select("'done' AS state")
|
||||
pending = grouped_count.where(state: :pending).select("'pending' AS state")
|
||||
union = unscoped.from_union([done, pending], remove_duplicates: false)
|
||||
.select(:user_id, :count, :state)
|
||||
|
||||
connection.select_all(union).each_with_object({}) do |row, counts|
|
||||
counts[[row['user_id'], row['state']]] = row['count']
|
||||
end
|
||||
# Count pending todos grouped by user_id and state
|
||||
# so we can utilize the index on state / user id.
|
||||
def pending_count_by_user_id
|
||||
where(state: :pending)
|
||||
.group(:user_id)
|
||||
.count(:id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2185,12 +2185,6 @@ class User < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def todos_done_count(force: false)
|
||||
Rails.cache.fetch(['users', id, 'todos_done_count'], force: force, expires_in: COUNT_CACHE_VALIDITY_PERIOD) do
|
||||
TodosFinder.new(self, state: :done).execute.count
|
||||
end
|
||||
end
|
||||
|
||||
def todos_pending_count(force: false)
|
||||
Rails.cache.fetch(['users', id, 'todos_pending_count'], force: force, expires_in: COUNT_CACHE_VALIDITY_PERIOD) do
|
||||
TodosFinder.new(self, state: :pending).execute.count
|
||||
|
|
@ -2204,7 +2198,6 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
def update_todos_count_cache
|
||||
todos_done_count(force: true)
|
||||
todos_pending_count(force: true)
|
||||
end
|
||||
|
||||
|
|
@ -2226,7 +2219,6 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
def invalidate_todos_cache_counts
|
||||
Rails.cache.delete(['users', id, 'todos_done_count'])
|
||||
Rails.cache.delete(['users', id, 'todos_pending_count'])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,25 +13,18 @@ module Users
|
|||
|
||||
def execute
|
||||
user_ids.each_slice(QUERY_BATCH_SIZE) do |user_ids_batch|
|
||||
todo_counts = Todo.for_user(user_ids_batch).count_grouped_by_user_id_and_state
|
||||
todo_counts = Todo.for_user(user_ids_batch).pending_count_by_user_id
|
||||
|
||||
user_ids_batch.each do |user_id|
|
||||
update_count_cache(user_id, todo_counts, :done)
|
||||
update_count_cache(user_id, todo_counts, :pending)
|
||||
count = todo_counts.fetch(user_id, 0)
|
||||
|
||||
Rails.cache.write(
|
||||
['users', user_id, "todos_pending_count"],
|
||||
count,
|
||||
expires_in: User::COUNT_CACHE_VALIDITY_PERIOD
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_count_cache(user_id, todo_counts, state)
|
||||
count = todo_counts.fetch([user_id, state.to_s], 0)
|
||||
|
||||
Rails.cache.write(
|
||||
['users', user_id, "todos_#{state}_count"],
|
||||
count,
|
||||
expires_in: User::COUNT_CACHE_VALIDITY_PERIOD
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110010
|
|||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/389235
|
||||
milestone: '15.9'
|
||||
type: ops
|
||||
group: group::anti-abuse
|
||||
group: group::test governance
|
||||
default_enabled: false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexToProjectRequirementStatusNamesapceUpdatedId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.10'
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAMESPACE_ID = 'idx_project_requirement_statuses_on_namespace_id'
|
||||
INDEX_NAMESPACE_UPDATED_AT_ID_DESC = 'i_project_requirement_statuses_on_namespace_id_updated_at_id'
|
||||
|
||||
def up
|
||||
add_concurrent_index :project_requirement_compliance_statuses, [:namespace_id, :updated_at, :id],
|
||||
order: { updated_at: :desc, id: :desc }, using: :btree, name: INDEX_NAMESPACE_UPDATED_AT_ID_DESC
|
||||
|
||||
remove_concurrent_index_by_name :project_requirement_compliance_statuses, INDEX_NAMESPACE_ID
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :project_requirement_compliance_statuses, :namespace_id, name: INDEX_NAMESPACE_ID
|
||||
|
||||
remove_concurrent_index_by_name :project_requirement_compliance_statuses, INDEX_NAMESPACE_UPDATED_AT_ID_DESC
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
158ff3fc38ec0c89115fddab9f53b4b332eef85ca82d3d69db2ce6634c50e52d
|
||||
|
|
@ -31579,6 +31579,8 @@ CREATE UNIQUE INDEX i_pm_package_versions_on_package_id_and_version ON pm_packag
|
|||
|
||||
CREATE UNIQUE INDEX i_pm_packages_purl_type_and_name ON pm_packages USING btree (purl_type, name);
|
||||
|
||||
CREATE INDEX i_project_requirement_statuses_on_namespace_id_updated_at_id ON project_requirement_compliance_statuses USING btree (namespace_id, updated_at DESC, id DESC);
|
||||
|
||||
CREATE INDEX i_protected_branch_unprotect_access_levels_protected_branch_nam ON protected_branch_unprotect_access_levels USING btree (protected_branch_namespace_id);
|
||||
|
||||
CREATE INDEX i_protected_branch_unprotect_access_levels_protected_branch_pro ON protected_branch_unprotect_access_levels USING btree (protected_branch_project_id);
|
||||
|
|
@ -31905,8 +31907,6 @@ CREATE INDEX idx_project_repository_check_partial ON projects USING btree (repos
|
|||
|
||||
CREATE INDEX idx_project_requirement_statuses_on_framework_id ON project_requirement_compliance_statuses USING btree (compliance_framework_id);
|
||||
|
||||
CREATE INDEX idx_project_requirement_statuses_on_namespace_id ON project_requirement_compliance_statuses USING btree (namespace_id);
|
||||
|
||||
CREATE INDEX idx_projects_api_created_at_id_for_archived ON projects USING btree (created_at, id) WHERE ((archived = true) AND (pending_delete = false) AND (hidden = false));
|
||||
|
||||
CREATE INDEX idx_projects_api_created_at_id_for_archived_vis20 ON projects USING btree (created_at, id) WHERE ((archived = true) AND (visibility_level = 20) AND (pending_delete = false) AND (hidden = false));
|
||||
|
|
|
|||
|
|
@ -17818,6 +17818,29 @@ The edge type for [`PipelineTrigger`](#pipelinetrigger).
|
|||
| <a id="pipelinetriggeredgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="pipelinetriggeredgenode"></a>`node` | [`PipelineTrigger`](#pipelinetrigger) | The item at the end of the edge. |
|
||||
|
||||
#### `ProjectComplianceRequirementStatusConnection`
|
||||
|
||||
The connection type for [`ProjectComplianceRequirementStatus`](#projectcompliancerequirementstatus).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="projectcompliancerequirementstatusconnectionedges"></a>`edges` | [`[ProjectComplianceRequirementStatusEdge]`](#projectcompliancerequirementstatusedge) | A list of edges. |
|
||||
| <a id="projectcompliancerequirementstatusconnectionnodes"></a>`nodes` | [`[ProjectComplianceRequirementStatus]`](#projectcompliancerequirementstatus) | A list of nodes. |
|
||||
| <a id="projectcompliancerequirementstatusconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
|
||||
#### `ProjectComplianceRequirementStatusEdge`
|
||||
|
||||
The edge type for [`ProjectComplianceRequirementStatus`](#projectcompliancerequirementstatus).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="projectcompliancerequirementstatusedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="projectcompliancerequirementstatusedgenode"></a>`node` | [`ProjectComplianceRequirementStatus`](#projectcompliancerequirementstatus) | The item at the end of the edge. |
|
||||
|
||||
#### `ProjectConnection`
|
||||
|
||||
The connection type for [`Project`](#project).
|
||||
|
|
@ -26805,6 +26828,7 @@ GPG signature for a signed commit.
|
|||
| <a id="grouppendingmembers"></a>`pendingMembers` {{< icon name="warning-solid" >}} | [`PendingMemberInterfaceConnection`](#pendingmemberinterfaceconnection) | **Introduced** in GitLab 16.6. **Status**: Experiment. A pending membership of a user within this group. |
|
||||
| <a id="grouppermanentdeletiondate"></a>`permanentDeletionDate` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 16.11. **Status**: Experiment. Date when group will be deleted if delayed group deletion is enabled. |
|
||||
| <a id="groupproductanalyticsstoredeventslimit"></a>`productAnalyticsStoredEventsLimit` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 16.9. **Status**: Experiment. Number of product analytics events namespace is permitted to store per cycle. |
|
||||
| <a id="groupprojectcompliancerequirementsstatus"></a>`projectComplianceRequirementsStatus` {{< icon name="warning-solid" >}} | [`ProjectComplianceRequirementStatusConnection`](#projectcompliancerequirementstatusconnection) | **Introduced** in GitLab 17.10. **Status**: Experiment. Compliance standards adherence for the projects in a group and its subgroups. |
|
||||
| <a id="groupprojectcreationlevel"></a>`projectCreationLevel` | [`String`](#string) | Permission level required to create projects in the group. |
|
||||
| <a id="groupprojectscount"></a>`projectsCount` | [`Int!`](#int) | Count of direct projects in the group. |
|
||||
| <a id="grouprecentissueboards"></a>`recentIssueBoards` | [`BoardConnection`](#boardconnection) | List of recently visited boards of the group. Maximum size is 4. (see [Connections](#connections)) |
|
||||
|
|
@ -36254,6 +36278,23 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| <a id="projectcicdsettingproject"></a>`project` | [`Project`](#project) | Project the CI/CD settings belong to. |
|
||||
| <a id="projectcicdsettingpushrepositoryforjobtokenallowed"></a>`pushRepositoryForJobTokenAllowed` | [`Boolean`](#boolean) | Indicates the ability to push to the original project repository using a job token. |
|
||||
|
||||
### `ProjectComplianceRequirementStatus`
|
||||
|
||||
Compliance requirement status for a project.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="projectcompliancerequirementstatuscomplianceframework"></a>`complianceFramework` | [`ComplianceFramework!`](#complianceframework) | Framework of the compliance status. |
|
||||
| <a id="projectcompliancerequirementstatuscompliancerequirement"></a>`complianceRequirement` | [`ComplianceRequirement!`](#compliancerequirement) | Requirement of the compliance status. |
|
||||
| <a id="projectcompliancerequirementstatusfailcount"></a>`failCount` | [`Int!`](#int) | Total no. of failed compliance controls for the requirement. |
|
||||
| <a id="projectcompliancerequirementstatusid"></a>`id` | [`ID!`](#id) | Compliance requirement status ID. |
|
||||
| <a id="projectcompliancerequirementstatuspasscount"></a>`passCount` | [`Int!`](#int) | Total no. of passed compliance controls for the requirement. |
|
||||
| <a id="projectcompliancerequirementstatuspendingcount"></a>`pendingCount` | [`Int!`](#int) | Total no. of pending compliance controls for the requirement. |
|
||||
| <a id="projectcompliancerequirementstatusproject"></a>`project` | [`Project!`](#project) | Project of the compliance status. |
|
||||
| <a id="projectcompliancerequirementstatusupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp when the requirement status was last updated. |
|
||||
|
||||
### `ProjectDataTransfer`
|
||||
|
||||
#### Fields
|
||||
|
|
|
|||
|
|
@ -234,13 +234,17 @@ it_behaves_like 'internal event tracking' do
|
|||
end
|
||||
```
|
||||
|
||||
These legacy options are now deprecated:
|
||||
If present in the context, the following legacy options will be respected by the shared example but are discouraged:
|
||||
|
||||
- `label`
|
||||
- `property`
|
||||
- `value`
|
||||
|
||||
Prefer using `additional_properties` instead.
|
||||
Prefer including these attributes via `additional_properties` instead.
|
||||
|
||||
```ruby
|
||||
let(:additional_properties) { { label: "value" } }
|
||||
```
|
||||
|
||||
#### Composable matchers
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,14 @@ title: Configure GitLab Duo on a self-managed instance
|
|||
GitLab Duo is powered by large language models (LLMs), with data sent through an AI gateway.
|
||||
To use GitLab Duo on a self-managed instance, you can do either of the following:
|
||||
|
||||
- Use the LLMs and the cloud-based AI gateway that's hosted by GitLab. This is the default option.
|
||||
- [Use LLMs from the supported list and self-host the AI gateway and LLMs](../../administration/gitlab_duo_self_hosted/_index.md#set-up-a-gitlab-duo-self-hosted-infrastructure).
|
||||
- Use the GitLab AI vendor models and the cloud-based AI gateway that’s hosted by
|
||||
GitLab. This is the default option.
|
||||
- [Use GitLab Duo Self-Hosted to self-host the AI gateway, with a supported self-hosted LLM](../../administration/gitlab_duo_self_hosted/_index.md#set-up-a-gitlab-duo-self-hosted-infrastructure).
|
||||
This option provides full control over your data and security.
|
||||
|
||||
{{< alert type="note" >}}
|
||||
|
||||
You must have an Ultimate license with GitLab Duo Enterprise add-on to use GitLab Duo Self-Hosted.
|
||||
You must have an Ultimate subscription with the GitLab Duo Enterprise add-on to use GitLab Duo Self-Hosted.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ GitLab Duo features that are generally available are automatically turned on for
|
|||
[you must also assign seats](../../subscriptions/subscription-add-ons.md#assign-gitlab-duo-seats)
|
||||
to the users you want to have access.
|
||||
|
||||
{{< alert type="note" >}}
|
||||
|
||||
To turn on GitLab Duo Self-Hosted, see [Configure GitLab to access GitLab Duo Self-Hosted](../../administration/gitlab_duo_self_hosted/configure_duo_features.md).
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
## Turn off GitLab Duo features
|
||||
|
||||
You can turn off GitLab Duo for a group, project, or instance.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ title: Test a new look for issues
|
|||
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/9584) in GitLab 17.5 [with a flag](../../../administration/feature_flags.md) named `work_items_view_preference`. Disabled by default. This feature is in [beta](../../../policy/development_stages_support.md#beta).
|
||||
- Feature flag named `work_items_view_preference` enabled on GitLab.com in GitLab 17.9 for a subset of users.
|
||||
- Feature flag named `work_items_view_preference` [enabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184496) on GitLab Self-Managed and GitLab Dedicated in 17.10.
|
||||
- Feature flag named `work_items_view_preference` [enabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184496) on GitLab.com, GitLab Self-Managed, and GitLab Dedicated in 17.10.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -61043,9 +61043,6 @@ msgstr ""
|
|||
msgid "To-Do List"
|
||||
msgstr ""
|
||||
|
||||
msgid "To-do item successfully marked as done."
|
||||
msgstr ""
|
||||
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ RSpec.describe Todo, feature_category: :notifications do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.group_by_user_id_and_state' do
|
||||
describe '.pending_count_by_user_id' do
|
||||
before do
|
||||
create(:todo, user: user, state: :pending)
|
||||
create(:todo, user: user, state: :pending)
|
||||
|
|
@ -656,7 +656,7 @@ RSpec.describe Todo, feature_category: :notifications do
|
|||
end
|
||||
|
||||
specify do
|
||||
expect(described_class.count_grouped_by_user_id_and_state).to eq({ [user.id, "done"] => 1, [user.id, "pending"] => 2, [user2.id, "pending"] => 1 })
|
||||
expect(described_class.pending_count_by_user_id).to eq({ user.id => 2, user2.id => 1 })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3129,11 +3129,9 @@ RSpec.describe User, feature_category: :user_profile do
|
|||
|
||||
expect { user.ban }
|
||||
.to change { todo_users.map(&:todos_pending_count).uniq }.from([1]).to([0])
|
||||
.and not_change { todo_users.map(&:todos_done_count) }
|
||||
|
||||
expect { user.unban }
|
||||
.to change { todo_users.map(&:todos_pending_count).uniq }.from([0]).to([1])
|
||||
.and not_change { todo_users.map(&:todos_done_count) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ RSpec.describe Members::DestroyService, feature_category: :groups_and_projects d
|
|||
expect(member_user.assigned_open_merge_requests_count).to be(1)
|
||||
expect(member_user.assigned_open_issues_count).to be(1)
|
||||
expect(member_user.todos_pending_count).to be(1)
|
||||
expect(member_user.todos_done_count).to be(1)
|
||||
|
||||
service = described_class.new(current_user)
|
||||
|
||||
|
|
@ -91,7 +90,6 @@ RSpec.describe Members::DestroyService, feature_category: :groups_and_projects d
|
|||
expect(member_user.assigned_open_merge_requests_count).to be(0)
|
||||
expect(member_user.assigned_open_issues_count).to be(0)
|
||||
expect(member_user.todos_pending_count).to be(0)
|
||||
expect(member_user.todos_done_count).to be(0)
|
||||
|
||||
unless opts[:unassign_issuables]
|
||||
expect(member_user.assigned_merge_requests.opened.count).to be(1)
|
||||
|
|
|
|||
|
|
@ -365,13 +365,11 @@ RSpec.describe TodoService, feature_category: :notifications do
|
|||
it 'updates when todos change' do
|
||||
create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)
|
||||
|
||||
expect(john_doe.todos_done_count).to eq(0)
|
||||
expect(john_doe.todos_pending_count).to eq(1)
|
||||
expect(john_doe).to receive(:update_todos_count_cache).and_call_original
|
||||
|
||||
service.resolve_todos_for_target(issue, john_doe)
|
||||
|
||||
expect(john_doe.todos_done_count).to eq(1)
|
||||
expect(john_doe.todos_pending_count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
|
@ -790,13 +788,11 @@ RSpec.describe TodoService, feature_category: :notifications do
|
|||
it 'updates when todos change' do
|
||||
create(:todo, :assigned, user: john_doe, project: project, target: work_item, author: author)
|
||||
|
||||
expect(john_doe.todos_done_count).to eq(0)
|
||||
expect(john_doe.todos_pending_count).to eq(1)
|
||||
expect(john_doe).to receive(:update_todos_count_cache).and_call_original
|
||||
|
||||
service.resolve_todos_for_target(work_item, john_doe)
|
||||
|
||||
expect(john_doe.todos_done_count).to eq(1)
|
||||
expect(john_doe.todos_pending_count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
|
@ -1422,13 +1418,11 @@ RSpec.describe TodoService, feature_category: :notifications do
|
|||
|
||||
context 'cached counts' do
|
||||
it 'updates when todos change' do
|
||||
expect(john_doe.todos_done_count).to eq(0)
|
||||
expect(john_doe.todos_pending_count).to eq(1)
|
||||
expect(john_doe).to receive(:update_todos_count_cache).and_call_original
|
||||
|
||||
service.resolve_todo(todo, john_doe)
|
||||
|
||||
expect(john_doe.todos_done_count).to eq(1)
|
||||
expect(john_doe.todos_pending_count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
|
@ -1508,13 +1502,11 @@ RSpec.describe TodoService, feature_category: :notifications do
|
|||
|
||||
context 'cached counts' do
|
||||
it 'updates when todos change' do
|
||||
expect(john_doe.todos_done_count).to eq(1)
|
||||
expect(john_doe.todos_pending_count).to eq(0)
|
||||
expect(john_doe).to receive(:update_todos_count_cache).and_call_original
|
||||
|
||||
service.restore_todo(todo, john_doe)
|
||||
|
||||
expect(john_doe.todos_done_count).to eq(0)
|
||||
expect(john_doe.todos_pending_count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ RSpec.describe Todos::Destroy::DestroyedIssuableService, feature_category: :team
|
|||
it 'invalidates todos cache counts of todo users', :use_clean_rails_redis_caching do
|
||||
expect { subject }
|
||||
.to change { pending_todo.user.todos_pending_count }.from(1).to(0)
|
||||
.and change { done_todo.user.todos_done_count }.from(1).to(0)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -23,23 +23,17 @@ RSpec.describe Users::UpdateTodoCountCacheService, feature_category: :notificati
|
|||
end
|
||||
|
||||
it 'updates the todos_counts for users', :use_clean_rails_memory_store_caching do
|
||||
Rails.cache.write(['users', user1.id, 'todos_done_count'], 0)
|
||||
Rails.cache.write(['users', user1.id, 'todos_pending_count'], 0)
|
||||
Rails.cache.write(['users', user2.id, 'todos_done_count'], 0)
|
||||
Rails.cache.write(['users', user2.id, 'todos_pending_count'], 0)
|
||||
|
||||
expect { execute_all }
|
||||
.to change(user1, :todos_done_count).from(0).to(2)
|
||||
.and change(user1, :todos_pending_count).from(0).to(1)
|
||||
.and change(user2, :todos_done_count).from(0).to(1)
|
||||
.to change(user1, :todos_pending_count).from(0).to(1)
|
||||
.and change(user2, :todos_pending_count).from(0).to(2)
|
||||
|
||||
Todo.delete_all
|
||||
|
||||
expect { execute_all }
|
||||
.to change(user1, :todos_done_count).from(2).to(0)
|
||||
.and change(user1, :todos_pending_count).from(1).to(0)
|
||||
.and change(user2, :todos_done_count).from(1).to(0)
|
||||
.to change(user1, :todos_pending_count).from(1).to(0)
|
||||
.and change(user2, :todos_pending_count).from(2).to(0)
|
||||
end
|
||||
|
||||
|
|
@ -59,7 +53,7 @@ RSpec.describe Users::UpdateTodoCountCacheService, feature_category: :notificati
|
|||
it 'sets the correct cache expire time' do
|
||||
expect(Rails.cache).to receive(:write)
|
||||
.with(['users', user1.id, anything], anything, expires_in: User::COUNT_CACHE_VALIDITY_PERIOD)
|
||||
.twice
|
||||
.once
|
||||
|
||||
execute_single
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@
|
|||
# - additional_properties
|
||||
# - event_attribute_overrides - is used when its necessary to override the attributes available in parent context.
|
||||
#
|
||||
# These legacy options are now deprecated:
|
||||
# [Legacy] If present in the context, the following will be respected by the shared example but are discouraged:
|
||||
# - label
|
||||
# - property
|
||||
# - value
|
||||
# Prefer using additional_properties instead.
|
||||
# [Recommended] Prefer including these attributes via additional_properties instead.
|
||||
# ex) let(:additional_properties) { { label: "value" } }
|
||||
|
||||
RSpec.shared_examples 'internal event tracking' do
|
||||
let(:all_metrics) do
|
||||
|
|
|
|||
Loading…
Reference in New Issue