Skip to content

Commit 93fe450

Browse files
authored
Merge pull request #4095 from nspcc-dev/iterator
2 parents 88fdf41 + 486ebac commit 93fe450

File tree

5 files changed

+37
-26
lines changed

5 files changed

+37
-26
lines changed

docs/node-configuration.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,10 @@ where:
330330
(normally the limit for it is MaxVerificationGAS from Policy, but if MaxGasInvoke
331331
is lower than that then this limit is respected).
332332
- `MaxIteratorResultItems` - maximum number of elements extracted from iterator
333-
returned by `invoke*` call. When the `MaxIteratorResultItems` value is set to
334-
`n`, only `n` iterations are returned and truncated is true, indicating that
333+
returned by `invoke*` call in cases if `SessionEnabled` is false or
334+
`SessionExpansionEnabled` is true. When the `MaxIteratorResultItems` value is
335+
set to `n`, only `n` iterations are returned and truncated is true (if
336+
`SessionEnabled` is false, see `SessionEnabled` setting), indicating that
335337
there is still data to be returned.
336338
- `MaxFindResultItems` - the maximum number of elements for `findstates` response.
337339
- `MaxFindStoragePageSize` - the maximum number of elements for `findstorage` response per single page.
@@ -358,23 +360,26 @@ where:
358360
on the server side available for further traverse. `traverseiterator` and
359361
`terminatesession` JSON-RPC calls will be handled by the server. It is not
360362
recommended to enable this setting for public RPC servers due to possible DoS
361-
attack. Set to `false` by default. If `false`, iterators are expanded into a
362-
set of values (see `MaxIteratorResultItems` setting). Implementation note: when
363-
BoltDB storage is used as a node backend DB, then enabling iterator sessions may
364-
cause blockchain persist delays up to 2*`SessionLifetime` on
365-
early blockchain lifetime stages with relatively small DB size. It can happen
366-
due to BoltDB re-mmapping behaviour traits. If regular persist is a critical
367-
requirement, then we recommend either to decrease `SessionLifetime` or to
368-
enable `SessionBackedByMPT`, see `SessionBackedByMPT` documentation for more
363+
attack. Set to `false` by default. If `false` or `SessionExpansionEnabled`,
364+
iterators are expanded into a set of values (see `MaxIteratorResultItems` and
365+
`SessionExpansionEnabled` settings). Implementation note: when BoltDB storage
366+
is used as a node backend DB, then enabling iterator sessions may cause
367+
blockchain persist delays up to 2*`SessionLifetime` on early blockchain
368+
lifetime stages with relatively small DB size. It can happen due to BoltDB
369+
re-mmapping behaviour traits. If regular persist is a critical requirement,
370+
then we recommend either to decrease `SessionLifetime` or to enable
371+
`SessionBackedByMPT`, see `SessionBackedByMPT` documentation for more
369372
details.
370373
- `SessionExpansionEnabled` enables partial expansion of iterators returned by
371374
`invoke*` calls. When enabled, the server returns up to `MaxIteratorResultItems`
372375
values from the iterator in the initial response. If more items are available,
373-
the result is marked as truncated. When `SessionEnabled` is also true, the
374-
remaining iterator state is stored in a session, allowing further traversal
375-
via `traverseiterator`. If disabled, iterators are either expanded up to
376-
`MaxIteratorResultItems` or require explicit traversal via session-based calls.
377-
By default, `SessionExpansionEnabled` is set to `false`.
376+
the result is marked as truncated (if `SessionEnabled` is false). When
377+
`SessionEnabled` is also true, the remaining iterator state (if so) is stored
378+
in a session, allowing further traversal via `traverseiterator`; iterator ID
379+
field remains empty for cases when the iterator doesn't have more items after
380+
expansion. If disabled, iterators are either expanded up to
381+
`MaxIteratorResultItems` or require explicit traversal via session-based
382+
calls. By default, `SessionExpansionEnabled` is set to `false`.
378383
- `SessionLifetime` (`Duration`) is a lifetime of iterator session. It is set to
379384
`TimePerBlock` seconds (but not less than 5s) by default and is relevant
380385
only if `SessionEnabled` is set to `true`.

docs/rpc.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,10 @@ applicationlog. This behaviour differs from notifications which are omitted for
461461
The `SessionExpansionEnabled` configuration setting enforces RPC server to expand any iterator
462462
returned by `invoke*` calls. Specifically, up to `MaxIteratorResultItems` elements are
463463
returned in the initial response, and the returned iterator is marked as `Truncated` if the
464-
iterator contains more elements beyond the returned batch. In this case, if `SessionEnabled`
465-
is also `true`, an iterator `ID` and session `ID` is provided allowing clients to retrieve additional elements via
466-
`traverseiterator`. If SessionExpansionEnabled is false, the iterator behavior depends on
464+
iterator contains more elements beyond the returned batch and if iterator sessions are disabled.
465+
In this case, if `SessionEnabled` is also `true`, an iterator `ID` and session `ID` is provided
466+
instead of `Truncated` field allowing clients to retrieve additional elements via
467+
`traverseiterator`. If `SessionExpansionEnabled` is false, the iterator behavior depends on
467468
`SessionEnabled`: if `SessionEnabled` is `true`, a full iterator object with an ID is returned.
468469
If `SessionEnabled` is `false`, the iterator is expanded up to `MaxIteratorResultItems`.
469470

pkg/neorpc/result/invoke.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ type Iterator struct {
7070
// Values contains deserialized VM iterator values with a truncated flag. It may be non-nil
7171
// if session expansion is enabled (even when ID is set), or if the JSON-RPC server does not
7272
// support sessions but allows in-place iterator traversal.
73-
Values []stackitem.Item
73+
Values []stackitem.Item
74+
// Truncated indicates whether the iterator has more elements. It is set only if sessions
75+
// are disabled.
7476
Truncated bool
7577
}
7678

pkg/rpcclient/invoker/invoker.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ func iterateNext(rpc RPCSessions, sessionID uuid.UUID, iterator *result.Iterator
229229
}
230230

231231
var result []stackitem.Item
232-
233232
if iterator.Values != nil {
234233
count := min(num, len(iterator.Values))
235234
result = append(result, iterator.Values[:count]...)

pkg/services/rpcsrv/server.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,16 +2629,20 @@ func (s *Server) registerOrDumpIterator(item stackitem.Item) (stackitem.Item, uu
26292629
resIterator result.Iterator
26302630
curr stackitem.Item
26312631
)
2632+
if !s.config.SessionEnabled || s.config.SessionExpansionEnabled {
2633+
resIterator.Values, resIterator.Truncated, curr = iterator.ValuesTruncated(item, s.config.MaxIteratorResultItems)
2634+
}
26322635

2633-
if s.config.SessionEnabled {
2636+
// No point in holding iterator for further traversal if no more elements left after expansion.
2637+
if s.config.SessionEnabled && (!s.config.SessionExpansionEnabled || resIterator.Truncated) {
26342638
iterID = uuid.New()
26352639
resIterator.ID = &iterID
2636-
if s.config.SessionExpansionEnabled {
2637-
resIterator.Values, resIterator.Truncated, curr = iterator.ValuesTruncated(item, s.config.MaxIteratorResultItems)
2638-
}
2639-
} else {
2640-
resIterator.Values, resIterator.Truncated, curr = iterator.ValuesTruncated(item, s.config.MaxIteratorResultItems)
26412640
}
2641+
2642+
if s.config.SessionEnabled && s.config.SessionExpansionEnabled {
2643+
resIterator.Truncated = false // no sense in this field for session-based iterators.
2644+
}
2645+
26422646
return stackitem.NewInterop(resIterator), iterID, curr
26432647
}
26442648

0 commit comments

Comments
 (0)