application_limits.md 4.59 KB
Newer Older
Amy Qualls's avatar
Amy Qualls committed
1 2 3 4 5 6
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---

7 8 9 10 11 12 13 14
# Application limits development

This document provides a development guide for contributors to add application
limits to GitLab.

## Documentation

First of all, you have to gather information and decide which are the different
15
limits that are set for the different GitLab tiers. You also need to
16 17 18 19
coordinate with others to [document](../administration/instance_limits.md)
and communicate those limits.

There is a guide about [introducing application
20
limits](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits).
21 22 23 24 25

## Development

### Insert database plan limits

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
In the `plan_limits` table, create a new column and insert the limit values.
It's recommended to create two separate migration script files.

1. Add a new column to the `plan_limits` table with non-null default value that
   represents desired limit, such as:

   ```ruby
   add_column(:plan_limits, :project_hooks, :integer, default: 100, null: false)
   ```

   Plan limits entries set to `0` mean that limits are not enabled. You should
   use this setting only in special and documented circumstances.

1. (Optionally) Create the database migration that fine-tunes each level with a
   desired limit using `create_or_update_plan_limit` migration helper, such as:

   ```ruby
   class InsertProjectHooksPlanLimits < ActiveRecord::Migration[5.2]
     include Gitlab::Database::MigrationHelpers

     DOWNTIME = false

     def up
       create_or_update_plan_limit('project_hooks', 'default', 0)
       create_or_update_plan_limit('project_hooks', 'free', 10)
       create_or_update_plan_limit('project_hooks', 'bronze', 20)
       create_or_update_plan_limit('project_hooks', 'silver', 30)
       create_or_update_plan_limit('project_hooks', 'gold', 100)
     end

     def down
       create_or_update_plan_limit('project_hooks', 'default', 0)
       create_or_update_plan_limit('project_hooks', 'free', 0)
       create_or_update_plan_limit('project_hooks', 'bronze', 0)
       create_or_update_plan_limit('project_hooks', 'silver', 0)
       create_or_update_plan_limit('project_hooks', 'gold', 0)
     end
   end
   ```

66
   Some plans exist only on GitLab.com. This is a no-op for plans
67
   that do not exist.
68

69 70 71 72 73
### Plan limits validation

#### Get current limit

Access to the current limit can be done through the project or the namespace,
74
such as:
75 76 77 78 79 80 81 82 83 84

```ruby
project.actual_limits.project_hooks
```

#### Check current limit

There is one method `PlanLimits#exceeded?` to check if the current limit is
being exceeded. You can use either an `ActiveRecord` object or an `Integer`.

85
Ensures that the count of the records does not exceed the defined limit, such as:
86 87 88 89 90

```ruby
project.actual_limits.exceeded?(:project_hooks, ProjectHook.where(project: project))
```

91
Ensures that the number does not exceed the defined limit, such as:
92 93 94 95 96 97 98

```ruby
project.actual_limits.exceeded?(:project_hooks, 10)
```

#### `Limitable` concern

99
The [`Limitable` concern](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/limitable.rb)
100 101 102 103
can be used to validate that a model does not exceed the limits. It ensures
that the count of the records for the current model does not exceed the defined
limit.

104
You must specify the limit scope of the object being validated
105
and the limit name if it's different from the pluralized model name.
106 107 108 109

```ruby
class ProjectHook
  include Limitable
110 111 112 113 114 115 116 117 118 119 120

  self.limit_name = 'project_hooks' # Optional as ProjectHook corresponds with project_hooks
  self.limit_scope = :project
end
```

To test the model, you can include the shared examples.

```ruby
it_behaves_like 'includes Limitable concern' do
  subject { build(:project_hook, project: create(:project)) }
121 122
end
```
123

124 125 126 127 128 129 130 131 132 133 134 135 136 137
### Testing instance-wide limits

Instance-wide features always use `default` Plan, as instance-wide features
do not have license assigned.

```ruby
class InstanceVariable
  include Limitable

  self.limit_name = 'instance_variables' # Optional as InstanceVariable corresponds with instance_variables
  self.limit_scope = Limitable::GLOBAL_SCOPE
end
```

138 139
### Subscription Plans

140
Self-managed:
141 142 143

- `default` - Everyone

144
GitLab.com:
145

146 147 148 149 150
- `default` - Any system-wide feature
- `free` - Namespaces and projects with a Free subscription
- `bronze`- Namespaces and projects with a Bronze subscription
- `silver` - Namespaces and projects with a Silver subscription
- `gold` - Namespaces and projects with a Gold subscription
151

152
The `test` environment doesn't have any plans.