feat: expose Function call concurrency limits (#4956)

## Summary

Adds an optional `max_concurrency` setting to Function registration and
explicit refresh:

- A registered Function version can define the default maximum number of
user-code calls in flight for one logical execution.
- A refresh can override that default for that execution only.
- The value must be a positive `u32` and is independent from
`resource_budget`; it is not an account-wide quota.
- Omitting the option preserves the previous request payload. Local
embedded refreshes reject this Enterprise-only option.

Rust, Python sync/async, PyO3, and the existing Node refresh surface
forward the option. Node has no Function registration surface today, so
no registration API is added there. The generated TypeDoc pages are
included for the new public option.

## Validation

The native-tested source covers Function version decoding, registration
validation and serialization, the Flight SQL registration ticket and
returned version, remote refresh forwarding, local rejection, and Node's
numeric boundary before conversion. Exact stage results are Rust `1+3`
plus four remote cases at `1` each; Python `14/1/49/24`; Node `57`
remote and `1` local rejection. Ruff, standard repository Pyright, and
Biome passed.

The tested Python extension was
`21aa256a970f4a16ea8253d68401d0fc573d946412e8752155dfcad63f30654d`; the
tested Node addon and generated native declaration were
`f6089f861981f96f8ce0f6dbef43de0907b9eeb4b63e84cdd5da14e00d6cbd30` and
`4c4ceb205824075d706897c726c215dcf839880c757f0d0582d24cec5f938416`. The
final 24-file diff preserves the 22 tested
product/test/fixture/source-doc blobs and adds only two generated
TypeDoc pages.
This commit is contained in:
Xuanwo
2026-11-11 14:32:26 +08:00
committed by GitHub
parent 8029428c71
commit cf8e6d0fd4
24 changed files with 376 additions and 18 deletions
+20
View File
@@ -1621,6 +1621,22 @@ fn resource_budget_gpu_count(value: Option<f64>) -> napi::Result<u32> {
Ok(value as u32)
}
fn positive_u32(value: Option<f64>, name: &str) -> napi::Result<Option<u32>> {
value
.map(|value| {
if !value.is_finite()
|| value.fract() != 0.0
|| !(1.0..=u32::MAX as f64).contains(&value)
{
return Err(napi::Error::from_reason(format!(
"{name} must be an integer between 1 and 4294967295"
)));
}
Ok(value as u32)
})
.transpose()
}
/// Options for `Table.refreshColumn` and `Table.refreshColumnAsync`. Every
/// option is LanceDB Enterprise only; a LanceDB Embedded refresh ignores
/// `batchSize`, `gpuClass` and `gpuCount` and rejects the rest, including
@@ -1633,6 +1649,9 @@ pub struct RefreshColumnOptions {
pub where_clause: Option<String>,
/// Maximum rows per Function call; must be greater than zero.
pub batch_size: Option<u32>,
/// Override the registered Function's maximum concurrent user-code calls
/// for this logical execution.
pub max_concurrency: Option<f64>,
/// GPU class for Function workers.
pub gpu_class: Option<String>,
/// Complete aggregate CPU and memory budget for a registered Function
@@ -1666,6 +1685,7 @@ impl TryFrom<RefreshColumnOptions> for lancedb::table::RefreshColumnOptions {
let mut options = Self::default();
options.where_clause = value.where_clause;
options.batch_size = value.batch_size.map(|size| size as usize);
options.max_concurrency = positive_u32(value.max_concurrency, "maxConcurrency")?;
options.gpu_class = value.gpu_class;
options.resource_budget = value
.resource_budget