Skip to content

Commit 3ca24b2

Browse files
Add new error for rate limit
Adds RateLimitReached error, which is a Scylla-specific error returned when a per-partition rate limit is exceeded.
1 parent befd8b9 commit 3ca24b2

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

cassandra/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from enum import Enum
1516
import logging
1617

1718

@@ -728,3 +729,21 @@ class UnresolvableContactPoints(DriverException):
728729
contact points, only when lookup fails for all hosts
729730
"""
730731
pass
732+
733+
734+
class OperationType(Enum):
735+
Read = 0
736+
Write = 1
737+
738+
class RateLimitReached(ConfigurationException):
739+
'''
740+
Rate limit was exceeded for a partition affected by the request.
741+
'''
742+
op_type = None
743+
rejected_by_coordinator = False
744+
745+
def __init__(self, op_type=None, rejected_by_coordinator=False):
746+
self.op_type = op_type
747+
self.rejected_by_coordinator = rejected_by_coordinator
748+
message = f"[request_error_rate_limit_reached OpType={op_type.name} RejectedByCoordinator={rejected_by_coordinator}]"
749+
Exception.__init__(self, message)

cassandra/protocol.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
from six.moves import range
2323
import io
2424

25-
from cassandra import ProtocolVersion
25+
from cassandra import OperationType, ProtocolVersion
2626
from cassandra import type_codes, DriverException
27-
from cassandra import (Unavailable, WriteTimeout, ReadTimeout,
27+
from cassandra import (Unavailable, WriteTimeout, RateLimitReached, ReadTimeout,
2828
WriteFailure, ReadFailure, FunctionFailure,
2929
AlreadyExists, InvalidRequest, Unauthorized,
3030
UnsupportedOperation, UserFunctionDescriptor,
@@ -390,6 +390,19 @@ def recv_error_info(f, protocol_version):
390390
def to_exception(self):
391391
return AlreadyExists(**self.info)
392392

393+
class RateLimitReachedException(ConfigurationException):
394+
summary= 'Rate limit was exceeded for a partition affected by the request'
395+
error_code = 0x4321
396+
397+
@staticmethod
398+
def recv_error_info(f, protocol_version):
399+
return {
400+
'op_type': OperationType(read_byte(f)),
401+
'rejected_by_coordinator': read_byte(f) != 0
402+
}
403+
404+
def to_exception(self):
405+
return RateLimitReached(**self.info)
393406

394407
class ClientWriteError(RequestExecutionException):
395408
summary = 'Client write failure.'

docs/scylla-specific.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,39 @@ New Table Attributes
104104
105105
cluster.refresh_table_metadata("keyspace1", "standard1")
106106
assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
107+
108+
109+
New Error Types
110+
--------------------
111+
112+
* ``SCYLLA_RATE_LIMIT_ERROR`` Error
113+
114+
The ScyllaDB 5.1 introduced a feature called per-partition rate limiting. In case the (user defined) per-partition rate limit is exceeded, the database will start returning a Scylla-specific type of error: RateLimitReached.
115+
116+
.. code:: python
117+
118+
from cassandra import RateLimitReached
119+
from cassandra.cluster import Cluster
120+
121+
cluster = Cluster()
122+
session = cluster.connect()
123+
session.execute("""
124+
CREATE KEYSPACE IF NOT EXISTS keyspace1
125+
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}
126+
""")
127+
128+
session.execute("USE keyspace1")
129+
session.execute("""
130+
CREATE TABLE tbl (pk int PRIMARY KEY, v int)
131+
WITH per_partition_rate_limit = {'max_writes_per_second': 1}
132+
""")
133+
134+
prepared = session.prepare("""
135+
INSERT INTO tbl (pk, v) VALUES (?, ?)
136+
""")
137+
138+
try:
139+
for _ in range(1000):
140+
self.session.execute(prepared.bind((123, 456)))
141+
except RateLimitReached:
142+
raise

0 commit comments

Comments
 (0)