Skip to content

Commit

Permalink
Merge branch 'master' into named-visibility
Browse files Browse the repository at this point in the history
  • Loading branch information
rmosolgo committed Oct 4, 2024
2 parents 3c0eb04 + 6d57bba commit 3c367e5
Show file tree
Hide file tree
Showing 39 changed files with 754 additions and 110 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
bundler-cache: true
env:
BUNDLE_GEMFILE: ./spec/dummy/Gemfile
- run: bundle exec rails test:system
- run: bundle exec rails test:all
working-directory: ./spec/dummy
# Some coverage goals of these tests:
# - Test once without Rails at all
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG-enterprise.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@

### Bug Fix

# 1.5.3 (1 Oct 2024)

- Limiters: Add expiration to rate limit data (to reduce Redis footprint)

# 1.5.2 (6 Sept 2024)

- Limiters: Add `connection_pool:` support

# 1.5.1 (30 Aug 2024)

- ObjectCache: Add `connection_pool:` support
Expand Down
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,34 @@

### Bug fixes

# 2.3.16 (12 Sept 2024)

### Bug fixes

- RuboCop: fix `FieldTypeInBlock` for single-line classes #5098
- Testing: Add `context[:current_field]` to testing helpers #5096

# 2.3.15 (10 Sept 2024)

### New features

- Type definitions accept `comment("...")` for annotating SDL #5067
- Parser: add `tokens_count` method #5066
- Schema: allow `validate_timeout` to be reset #5062

### Bug fixes

- Optimize `Language.escape_single_quoted_newlines` #5095
- Generators: Add `# frozen_string_literal: true` to base resolver #5092
- Parser: Properly handle minus followed by name #5090
- Migrate some attr_reader methods #5080
- Handle variable definition directives #5072
- Handle `GraphQL::ExecutionError` when loading arguments during analysis #5071
- NotificationsTrace: properly call `super`
- Use symbols for namespaced_types generator option #5068
- Reduce memory usage in lazy resolution #5061
- Fix default trace inheritance #5045

# 2.3.14 (13 Aug 2024)

### Bug fixes
Expand Down
32 changes: 1 addition & 31 deletions guides/limiters/active_operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ end

It also accepts a `stale_request_seconds:` option. The limiter uses that value to clean up request data in case of a crash or other unexpected scenario.

Before requests will actually be halted, ["soft mode"](#soft-limits) must be disabled as described below.
Before requests will actually be halted, {% internal_link "soft mode", "/limiters/deployment#soft-limits" %} must be disabled.

#### Query Setup

Expand All @@ -57,36 +57,6 @@ Operations with the same `context[:limiter_key]` will rate limited in the same b

To provide a client identifier another way, see [Customization](#customization).

## Soft Limits

By default, the limiter doesn't actually halt queries; instead, it starts out in "soft mode". In this mode:

- limited/unlimited requests are counted in the [Dashboard](#dashboard)
- but, no requests are actually halted

This mode is for assessing the impact of the limiter before it's applied to production traffic. Additionally, if you release the limiter but find that it's affecting production traffic adversely, you can re-enable "soft mode" to stop blocking traffic.

To disable "soft mode" and start limiting, use the [Dashboard](#dashboard) or [customize the limiter](#customization). You can also disable "soft mode" in Ruby:

```ruby
# Turn "soft mode" off for the ActiveOperationLimiter
MySchema.enterprise_active_operation_limiter.set_soft_limit(false)
```

## Dashboard

Once installed, your {% internal_link "GraphQL-Pro dashboard", "/pro/dashboard" %} will include a simple metrics view:

{{ "/limiters/active_operation_limiter_dashboard.png" | link_to_img:"GraphQL Active Operation Limiter Dashboard" }}

See [Instrumentation](#instrumentation) below for more details on limiter metrics. To disable dashboard charts, add `use(... dashboard_charts: false)` to your configuration.

Also, the dashboard includes a link to enable or disable "soft mode":

{{ "/limiters/soft_button.png" | link_to_img:"GraphQL Rate Limiter Soft Mode Button" }}

When "soft mode" is enabled, limited requests are _not_ actually halted (although they are _counted_). When "soft mode" is disabled, any over-limit requests are halted.

## Customization

`GraphQL::Enterprise::ActiveOperationLimiter` provides several hooks for customizing its behavior. To use these, make a subclass of the limiter and override methods as described:
Expand Down
94 changes: 94 additions & 0 deletions guides/limiters/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
layout: guide
doc_stub: false
search: true
enterprise: true
section: GraphQL Enterprise - Rate Limiters
title: Deploying Rate Limiters
desc: Tips for releasing limiters smoothly
index: 4
---

Here are a few options for deploying GraphQL-Enterprise's rate limiters:


- The [Dashboard](#dashboard) shows some basic metrics about the limiter.
- [Soft limits](#soft-limits) start logging over-limit requests to the dashboard but don't actually halt traffic.
- [Subscriptions](#subscriptions) need extra consideration


## Dashboard

Once installed, your {% internal_link "GraphQL-Pro dashboard", "/pro/dashboard" %} will include a simple metrics view:

{{ "/limiters/active_operation_limiter_dashboard.png" | link_to_img:"GraphQL Active Operation Limiter Dashboard" }}

To disable dashboard charts, add `use(... dashboard_charts: false)` to your configuration.

Also, the dashboard includes a link to enable or disable "soft mode":

{{ "/limiters/soft_button.png" | link_to_img:"GraphQL Rate Limiter Soft Mode Button" }}

When "soft mode" is enabled, limited requests are _not_ actually halted (although they are _counted_). When "soft mode" is disabled, any over-limit requests are halted.

For more detailed metrics, see the "Instrumentation" section of the documentation for each limiter.

## Soft Limits

By default, limiters don't actually halt queries; instead, they start out in "soft mode". In this mode:

- limited/unlimited requests are counted in the [Dashboard](#dashboard)
- but, no requests are actually halted

This mode is for assessing the impact of the limiter before it's applied to production traffic. Additionally, if you release the limiter but find that it's affecting production traffic adversely, you can re-enable "soft mode" to stop blocking traffic.

To disable "soft mode" and start limiting, use the [Dashboard](#dashboard) or re-implement some of the customization methods of the limiter.

You can also disable "soft mode" in Ruby:

```ruby
# Turn "soft mode" off for the ActiveOperationLimiter
MySchema.enterprise_active_operation_limiter.set_soft_limit(false)
# or, for RuntimeLimiter
MySchema.enterprise_runtime_limiter.set_soft_limit(false)
```


## Subscriptions

If you're using {% internal_link "PusherSubscriptions", "/subscriptions/pusher_implementation" %} or {% internal_link "AblySubscriptions", "/subscriptions/ably_implementation" %}, then you'll need to accomodate subscriptions that were created _before_ you deployed the rate limiter. Those subscriptions are already stored in Redis and their contexts _don't_ include the required `limiter_key:` value.

To address this, you can customize the limiter(s) you're using to provide a default value in this case. For example:

```ruby
class CustomRuntimeLimiter < GraphQL::Enterprise::RuntimeLimiter
def limiter_key(query)
if query.subscription_update? && query.context[:limiter_key].nil?
# This subscription was created before limiter_key was required,
# so provide a value for it.
# If `context` includes enough information to create a
# "real" limiter key, you could also do that here.
# In this case, we're providing a default flag:
"legacy-subscription-update"
else
super
end
end

def limit_for(key, query)
if key == "legacy-subscription-update"
nil # no limit in this case
else
super
end
end
end
```

With methods like that, any subscriptions created _before_ `limiter_key:` was required will not be subject to rate limits. Adjust those methods as needed for your application. Finally, be sure to attach your custom limiter in your schema, for example:


```ruby
# Use a custom subclass of GraphQL::Enterprise::RuntimeLimiter:
use CustomRuntimeLimiter, ...
```
33 changes: 1 addition & 32 deletions guides/limiters/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ end

It also accepts a `window_ms:` option, which is the duration over which `limit_ms:` is added to a client's bucket. It defaults to `60_000` (one minute).

Before requests will actually be halted, ["soft mode"](#soft-limits) must be disabled as described below.
Before requests will actually be halted, {% internal_link "soft mode", "/limiters/deployment#soft-limits" %} must be disabled.

### Query Setup

Expand All @@ -57,37 +57,6 @@ Operations with the same `context[:limiter_key]` will rate limited in the same b

To provide a client identifier another way, see [Customization](#customization).

## Soft Limits

By default, the limiter doesn't actually halt queries; instead, it starts out in "soft mode". In this mode:

- limited/unlimited requests are counted in the [Dashboard](#dashboard)
- but, no requests are actually halted

This mode is for assessing the impact of the limiter before it's applied to production traffic. Additionally, if you release the limiter but find that it's affecting production traffic adversely, you can re-enable "soft mode" to stop blocking traffic.

To disable "soft mode" and start limiting, use the [Dashboard](#dashboard) or [customize the limiter](#customization). You can also disable "soft mode" in Ruby:

```ruby
# Turn "soft mode" off for the RuntimeLimiter
MySchema.enterprise_runtime_limiter.set_soft_limit(false)
```


## Dashboard

Once installed, your {% internal_link "GraphQL-Pro dashboard", "/pro/dashboard" %} will include a simple metrics view:

{{ "/limiters/runtime_limiter_dashboard.png" | link_to_img:"GraphQL Runtime Limiter Dashboard" }}

See [Instrumentation](#instrumentation) below for more details on limiter metrics. To disable dashboard charts, add `use(... dashboard_charts: false)` to your configuration.

Also, the dashboard includes a link to enable or disable "soft mode":

{{ "/limiters/soft_button.png" | link_to_img:"GraphQL Rate Limiter Soft Mode Button" }}

When "soft mode" is enabled, limited requests are _not_ actually halted (although they are _counted_). When "soft mode" is disabled, any over-limit requests are halted.

## Customization

`GraphQL::Enterprise::RuntimeLimiter` provides several hooks for customizing its behavior. To use these, make a subclass of the limiter and override methods as described:
Expand Down
1 change: 1 addition & 0 deletions guides/pro/checksums/graphql-enterprise-1.5.2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e56b5290ed8798c67ca8e2fb1d6af8895570893e4c71e7958f3051dfa24617ec7772d325e44f54dc320f2963e802b28ba8036f26a4932971c5b9a2181bd98c6b
1 change: 1 addition & 0 deletions guides/pro/checksums/graphql-enterprise-1.5.3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
92d3392668d3365d61d31d1906f19e54b4cc330383a2876997ed3cefa787cbcd51f009b6a30181f0631ee6a80a3402549f44d4905145aadeb7abe421167daa6c
2 changes: 2 additions & 0 deletions guides/schema/object_identification.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class MySchema < GraphQL::Schema
end
```

> [SQIDs](https://sqids.org/ruby) are an alternative to `to_gid_param` which generate shorter IDs. Here is a [detailed guide](https://blog.gripdev.xyz/2024/06/09/sqids-graphql-and-ruby/) of how they can be used.
## Node interface

One requirement for Relay's object management is implementing the `"Node"` interface.
Expand Down
2 changes: 1 addition & 1 deletion guides/testing/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ desc: Running GraphQL fields in isolation
index: 3
---

GraphQL-Ruby ships with a test helper method, `run_graphql_field`, that can execute a GraphQL field in isolation. It use it in your test suite, include a module, with your schema class:
GraphQL-Ruby ships with a test helper method, `run_graphql_field`, that can execute a GraphQL field in isolation. To use it in your test suite, include the module with your schema class:

```ruby
# Mix in `run_graphql_field(...)` to run on `MySchema`
Expand Down
4 changes: 4 additions & 0 deletions javascript_client/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# graphql-ruby-client

# 1.14.1 (30 Sept 2024)

- `AblyLink`: don't set up an Ably subscription when no Subscription header is present #5113

# 1.14.0 (3 Jul 2024)

- Subscriptions: with Relay and ActionCable, don't send an empty query string (`""`) when using persisted operations #5008
Expand Down
2 changes: 1 addition & 1 deletion javascript_client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "graphql-ruby-client",
"version": "1.14.0",
"version": "1.14.1",
"description": "JavaScript client for graphql-ruby",
"main": "index.js",
"types": "index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion javascript_client/src/subscriptions/AblyLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class AblyLink extends ApolloLink {
forward(operation).subscribe({ next: (data) => {
// If the operation has the subscription header, it's a subscription
const subscriptionChannelConfig = this._getSubscriptionChannel(operation)
if (subscriptionChannelConfig) {
if (subscriptionChannelConfig.channel) {
// This will keep pushing to `.next`
this._createSubscription(subscriptionChannelConfig, observer)
}
Expand Down
Loading

0 comments on commit 3c367e5

Please sign in to comment.