@miosa/sdk 3.3.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +186 -11
- package/dist/index.js +271 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as ws from 'ws';
|
|
2
2
|
import EventEmitter from 'node:events';
|
|
3
|
+
import * as http2 from 'node:http2';
|
|
3
4
|
|
|
4
5
|
interface RequestOptions {
|
|
5
6
|
method?: string;
|
|
@@ -2243,6 +2244,13 @@ interface MiosaClientConfig {
|
|
|
2243
2244
|
region?: string;
|
|
2244
2245
|
/** Overrides `miosa.ai` - for self-hosted / test deployments. */
|
|
2245
2246
|
baseDomain?: string;
|
|
2247
|
+
/**
|
|
2248
|
+
* Pin each runner session group to one resolved IPv4 address, so
|
|
2249
|
+
* `run-<region>.miosa.ai`'s several A records are all used. Set `false`
|
|
2250
|
+
* to dial the hostname and let the OS resolver choose instead.
|
|
2251
|
+
* Defaults to `true`.
|
|
2252
|
+
*/
|
|
2253
|
+
pinAddresses?: boolean;
|
|
2246
2254
|
};
|
|
2247
2255
|
}
|
|
2248
2256
|
|
|
@@ -8855,8 +8863,22 @@ interface RunnerClientOptions {
|
|
|
8855
8863
|
tenant?: string;
|
|
8856
8864
|
/** Sessions opened per resolved region address. C6 default: 8. */
|
|
8857
8865
|
sessionsPerAddress?: number;
|
|
8866
|
+
/**
|
|
8867
|
+
* Pin each session group to one resolved runner address (C6), so creates
|
|
8868
|
+
* spread over every host behind `run-<region>.miosa.ai`. Set `false` to
|
|
8869
|
+
* dial the hostname and let the OS resolver choose instead. Defaults to
|
|
8870
|
+
* `true`; only consulted when `transport` is not injected.
|
|
8871
|
+
*/
|
|
8872
|
+
pinAddresses?: boolean;
|
|
8858
8873
|
/** Injectable for tests; defaults to the best available transport. */
|
|
8859
8874
|
transport?: RunnerTransport;
|
|
8875
|
+
/**
|
|
8876
|
+
* Race HTTP/3 against HTTP/2 per region host. Default false: HTTP/2 only.
|
|
8877
|
+
* See transport-factory.ts for why the race is opt-in - on a cold burst the
|
|
8878
|
+
* promotion can land requests on HTTP/3 sessions that are not yet carrying
|
|
8879
|
+
* traffic, which costs several times what HTTP/2 does.
|
|
8880
|
+
*/
|
|
8881
|
+
http3?: boolean;
|
|
8860
8882
|
/**
|
|
8861
8883
|
* Called for a create the runner doesn't serve (C2: template, image,
|
|
8862
8884
|
* snapshot, cwd, persistent, non-xs shapes) - wired by `Miosa` to
|
|
@@ -9003,6 +9025,13 @@ declare class RunnerClient {
|
|
|
9003
9025
|
private readonly addressIndexByTag;
|
|
9004
9026
|
/** sandbox id -> tag, set only once a 421 corrects the id-derived guess. */
|
|
9005
9027
|
private readonly correctedTag;
|
|
9028
|
+
/**
|
|
9029
|
+
* Rotating start address for creates, so a cold burst spreads over every
|
|
9030
|
+
* resolved runner address instead of all of it landing on address 0.
|
|
9031
|
+
* Advanced once per create; the retry on `429 runtime_busy`/connect
|
|
9032
|
+
* failure still walks the other addresses from there.
|
|
9033
|
+
*/
|
|
9034
|
+
private createCursor;
|
|
9006
9035
|
constructor(options: RunnerClientOptions);
|
|
9007
9036
|
get protocol(): RunnerProtocol;
|
|
9008
9037
|
/** The tag a 421 has corrected sandboxId to, if any. */
|
|
@@ -9510,17 +9539,32 @@ declare function sandboxTag(sandboxId: string): string;
|
|
|
9510
9539
|
/** Resolves a hostname to the list of IP addresses it should be reached at. */
|
|
9511
9540
|
interface AddressResolver {
|
|
9512
9541
|
resolve(hostname: string): Promise<string[]>;
|
|
9542
|
+
/**
|
|
9543
|
+
* Forgets anything cached for `hostname`, so the next `resolve` asks the
|
|
9544
|
+
* OS resolver again. The transports call this after a per-address connect
|
|
9545
|
+
* failure: a runner host that has moved, or whose address has gone away,
|
|
9546
|
+
* is re-resolved rather than retried at a stale address for the rest of
|
|
9547
|
+
* the cache window. Optional - a resolver with nothing to cache omits it.
|
|
9548
|
+
*/
|
|
9549
|
+
invalidate?(hostname: string): void;
|
|
9513
9550
|
}
|
|
9551
|
+
/** Resolves a hostname straight to its list of IPv4 addresses, in resolver order. */
|
|
9552
|
+
type AddressLookup = (hostname: string) => Promise<string[]>;
|
|
9514
9553
|
/**
|
|
9515
|
-
* Default resolver:
|
|
9516
|
-
*
|
|
9517
|
-
*
|
|
9554
|
+
* Default resolver: every IPv4 address of the hostname, cached for a short
|
|
9555
|
+
* TTL (60 s - the runners' advertised A-record TTL) so a burst of requests
|
|
9556
|
+
* resolves once instead of hitting the resolver per request. IP literals
|
|
9557
|
+
* and `localhost` are passed through unchanged so tests and self-hosted
|
|
9558
|
+
* runners can point the transport straight at a fixed address without a
|
|
9559
|
+
* resolver.
|
|
9518
9560
|
*/
|
|
9519
9561
|
declare class DnsAddressResolver implements AddressResolver {
|
|
9520
9562
|
private readonly ttlMs;
|
|
9563
|
+
private readonly lookupAddresses;
|
|
9521
9564
|
private readonly cache;
|
|
9522
|
-
constructor(ttlMs?: number);
|
|
9565
|
+
constructor(ttlMs?: number, lookupAddresses?: AddressLookup);
|
|
9523
9566
|
resolve(hostname: string): Promise<string[]>;
|
|
9567
|
+
invalidate(hostname: string): void;
|
|
9524
9568
|
}
|
|
9525
9569
|
/** A fixed-table resolver, for tests and for pinning to known runner IPs (C1). */
|
|
9526
9570
|
declare class StaticAddressResolver implements AddressResolver {
|
|
@@ -9551,8 +9595,23 @@ declare class StaticAddressResolver implements AddressResolver {
|
|
|
9551
9595
|
* coalescing: the cert covers `run-<region>.miosa.ai` and
|
|
9552
9596
|
* `*.run-<region>.miosa.ai`, and a per-host name's one A record is the
|
|
9553
9597
|
* same IP already in this pool - see transport.ts's doc comment).
|
|
9598
|
+
*
|
|
9599
|
+
* Pinning is what makes the dial target explicit: the hostname is resolved
|
|
9600
|
+
* once, and every session dials its own resolved IP while SNI and the
|
|
9601
|
+
* HTTP/2 `:authority` stay the hostname, so a name with several A records
|
|
9602
|
+
* spreads over all of them deterministically instead of wherever the OS
|
|
9603
|
+
* resolver happens to point. `pinAddresses: false` turns this off and dials
|
|
9604
|
+
* the hostname itself, letting the OS resolver choose (one address, the
|
|
9605
|
+
* pre-pinning behaviour). A per-address connect failure drops that
|
|
9606
|
+
* address's sessions, invalidates the resolver's cache and re-resolves, so
|
|
9607
|
+
* a host that has moved is not retried at a stale address.
|
|
9554
9608
|
*/
|
|
9555
9609
|
|
|
9610
|
+
/**
|
|
9611
|
+
* The dial itself, injectable so tests can observe (and selectively fail)
|
|
9612
|
+
* which address a session is opened against without a real socket.
|
|
9613
|
+
*/
|
|
9614
|
+
type Http2Connector = (authority: string, options: http2.SecureClientSessionOptions) => http2.ClientHttp2Session;
|
|
9556
9615
|
interface Http2TransportOptions {
|
|
9557
9616
|
/** Sessions opened per address when no explicit count is given. C6 default: 8. */
|
|
9558
9617
|
defaultSessionsPerAddress?: number;
|
|
@@ -9562,6 +9621,17 @@ interface Http2TransportOptions {
|
|
|
9562
9621
|
resolver?: AddressResolver;
|
|
9563
9622
|
/** Default per-request timeout when the caller doesn't set one. */
|
|
9564
9623
|
defaultTimeoutMs?: number;
|
|
9624
|
+
/**
|
|
9625
|
+
* Pin every session group to one resolved IPv4 address (C6), so a name
|
|
9626
|
+
* with several A records is dialled at all of them deliberately. Set
|
|
9627
|
+
* `false` to dial the hostname itself and let the OS resolver pick - the
|
|
9628
|
+
* pre-pinning behaviour, one address only. Defaults to `true`.
|
|
9629
|
+
*/
|
|
9630
|
+
pinAddresses?: boolean;
|
|
9631
|
+
/** Skips TLS certificate verification. Test-only - never set true in production. */
|
|
9632
|
+
insecure?: boolean;
|
|
9633
|
+
/** Injectable for tests; defaults to `node:http2`'s connect. */
|
|
9634
|
+
connect?: Http2Connector;
|
|
9565
9635
|
}
|
|
9566
9636
|
declare class Http2Transport implements RunnerTransport {
|
|
9567
9637
|
readonly protocol: "h2";
|
|
@@ -9570,6 +9640,9 @@ declare class Http2Transport implements RunnerTransport {
|
|
|
9570
9640
|
private readonly port;
|
|
9571
9641
|
private readonly resolver;
|
|
9572
9642
|
private readonly defaultTimeoutMs;
|
|
9643
|
+
private readonly pinAddresses;
|
|
9644
|
+
private readonly insecure;
|
|
9645
|
+
private readonly dial;
|
|
9573
9646
|
private readonly pools;
|
|
9574
9647
|
constructor(options?: Http2TransportOptions);
|
|
9575
9648
|
prewarm(regionHostname: string, sessionsPerAddress?: number): void;
|
|
@@ -9582,6 +9655,37 @@ declare class Http2Transport implements RunnerTransport {
|
|
|
9582
9655
|
close(): Promise<void>;
|
|
9583
9656
|
private poolFor;
|
|
9584
9657
|
private buildPool;
|
|
9658
|
+
/**
|
|
9659
|
+
* The addresses this pool pins to. With pinning on, every IPv4 address
|
|
9660
|
+
* the hostname resolves to; with it off, the hostname itself - one entry,
|
|
9661
|
+
* dialled as-is so the OS resolver chooses.
|
|
9662
|
+
*/
|
|
9663
|
+
private resolveAddresses;
|
|
9664
|
+
/**
|
|
9665
|
+
* Opens `sessionsPerAddress` sessions against one address, in parallel.
|
|
9666
|
+
* sessionsPerAddress: 0 is a deliberate "open nothing" (e.g. a count-only
|
|
9667
|
+
* probe).
|
|
9668
|
+
*/
|
|
9669
|
+
private openGroup;
|
|
9670
|
+
/** Closes a session slot once it connects, ignoring one that never did. */
|
|
9671
|
+
private closeSlot;
|
|
9672
|
+
/**
|
|
9673
|
+
* A session pinned to `address` failed to connect. Mark that address's
|
|
9674
|
+
* group for reopening and re-resolve in the background (single-flight),
|
|
9675
|
+
* so one dead address never costs every concurrent failure its own DNS
|
|
9676
|
+
* lookup. Never blocks or fails the request that is already on its way
|
|
9677
|
+
* out - the caller retries another index (C6's next-IP retry).
|
|
9678
|
+
*/
|
|
9679
|
+
private noteAddressFailure;
|
|
9680
|
+
/**
|
|
9681
|
+
* Re-resolves `regionHostname` and redistributes the pool over the fresh
|
|
9682
|
+
* addresses: the failed address's sessions are dropped and reopened, a
|
|
9683
|
+
* newly advertised address gets a group of its own, an address DNS no
|
|
9684
|
+
* longer lists loses its sessions, and every healthy address keeps the
|
|
9685
|
+
* sessions it already has - so a failure on one host never costs the rest
|
|
9686
|
+
* their warm connections.
|
|
9687
|
+
*/
|
|
9688
|
+
private rebuildPool;
|
|
9585
9689
|
private connectSession;
|
|
9586
9690
|
private sendRequest;
|
|
9587
9691
|
private sendStreamRequest;
|
|
@@ -9611,6 +9715,12 @@ interface Http3Availability {
|
|
|
9611
9715
|
declare function detectHttp3Support(): Http3Availability;
|
|
9612
9716
|
/** Exposed for tests - clears the cached load result and availability. */
|
|
9613
9717
|
declare function resetHttp3DetectionCache(): void;
|
|
9718
|
+
/**
|
|
9719
|
+
* The connection handshake, injectable so tests can observe (and
|
|
9720
|
+
* selectively fail) which address a connection is opened against without a
|
|
9721
|
+
* native QUIC listener.
|
|
9722
|
+
*/
|
|
9723
|
+
type Http3Connector = (address: string, servername: string, port: number, insecure: boolean, connectTimeoutMs: number) => Promise<number>;
|
|
9614
9724
|
interface Http3TransportOptions {
|
|
9615
9725
|
/** Sessions opened per address when no explicit count is given. C6: 4. */
|
|
9616
9726
|
defaultSessionsPerAddress?: number;
|
|
@@ -9626,6 +9736,17 @@ interface Http3TransportOptions {
|
|
|
9626
9736
|
/** Skips certificate verification. Test-only - never set true in production. */
|
|
9627
9737
|
insecure?: boolean;
|
|
9628
9738
|
port?: number;
|
|
9739
|
+
/**
|
|
9740
|
+
* Pin every connection group to one resolved IPv4 address (C6), so a name
|
|
9741
|
+
* with several A records is dialled at all of them deliberately. Set
|
|
9742
|
+
* `false` to use only the hostname's first resolved address and let the
|
|
9743
|
+
* OS resolver pick which that is - one target, the pre-pinning shape (the
|
|
9744
|
+
* native addon dials a literal address, so a hostname cannot be passed
|
|
9745
|
+
* through here). Defaults to `true`.
|
|
9746
|
+
*/
|
|
9747
|
+
pinAddresses?: boolean;
|
|
9748
|
+
/** Injectable for tests; defaults to the native addon's connect. */
|
|
9749
|
+
connect?: Http3Connector;
|
|
9629
9750
|
}
|
|
9630
9751
|
declare class Http3Transport implements RunnerTransport {
|
|
9631
9752
|
readonly protocol: "h3";
|
|
@@ -9636,6 +9757,8 @@ declare class Http3Transport implements RunnerTransport {
|
|
|
9636
9757
|
private readonly connectTimeoutMs;
|
|
9637
9758
|
private readonly insecure;
|
|
9638
9759
|
private readonly port;
|
|
9760
|
+
private readonly pinAddresses;
|
|
9761
|
+
private readonly dial;
|
|
9639
9762
|
private readonly pools;
|
|
9640
9763
|
constructor(options?: Http3TransportOptions);
|
|
9641
9764
|
prewarm(regionHostname: string, sessionsPerAddress?: number): void;
|
|
@@ -9654,23 +9777,67 @@ declare class Http3Transport implements RunnerTransport {
|
|
|
9654
9777
|
close(): Promise<void>;
|
|
9655
9778
|
private poolFor;
|
|
9656
9779
|
private buildPool;
|
|
9780
|
+
/**
|
|
9781
|
+
* The addresses this pool pins to. With pinning on, every IPv4 address
|
|
9782
|
+
* the hostname resolves to. With it off, the hostname is resolved once
|
|
9783
|
+
* and only its first address is kept - one target, chosen by the OS
|
|
9784
|
+
* resolver, which is the closest this transport can get to HTTP/2's
|
|
9785
|
+
* hostname dial: the native addon takes a literal socket address, never
|
|
9786
|
+
* a hostname.
|
|
9787
|
+
*/
|
|
9788
|
+
private resolveAddresses;
|
|
9789
|
+
/** Opens `sessionsPerAddress` connections against one address, in parallel. */
|
|
9790
|
+
private openGroup;
|
|
9791
|
+
/** Closes a connection slot once it connects, ignoring one that never did. */
|
|
9792
|
+
private closeSlot;
|
|
9793
|
+
/**
|
|
9794
|
+
* A connection pinned to `address` failed to connect. Mark that address's
|
|
9795
|
+
* group for reopening and re-resolve in the background (single-flight),
|
|
9796
|
+
* so one dead address never costs every concurrent failure its own DNS
|
|
9797
|
+
* lookup. Never blocks or fails the request already on its way out.
|
|
9798
|
+
*/
|
|
9799
|
+
private noteAddressFailure;
|
|
9800
|
+
/**
|
|
9801
|
+
* Re-resolves `regionHostname` and redistributes the pool over the fresh
|
|
9802
|
+
* addresses: the failed address's connections are dropped and reopened, a
|
|
9803
|
+
* newly advertised address gets a group of its own, an address DNS no
|
|
9804
|
+
* longer lists loses its connections, and every healthy address keeps the
|
|
9805
|
+
* connections it already has.
|
|
9806
|
+
*/
|
|
9807
|
+
private rebuildPool;
|
|
9657
9808
|
private connectSession;
|
|
9658
9809
|
private sendRequest;
|
|
9659
9810
|
}
|
|
9660
9811
|
|
|
9661
9812
|
/**
|
|
9662
|
-
* Picks the
|
|
9663
|
-
*
|
|
9664
|
-
*
|
|
9665
|
-
*
|
|
9666
|
-
*
|
|
9667
|
-
*
|
|
9668
|
-
* HTTP/2
|
|
9813
|
+
* Picks the transport for a region host.
|
|
9814
|
+
*
|
|
9815
|
+
* HTTP/2 unless the caller opts into racing HTTP/3 against it. A platform
|
|
9816
|
+
* with no native HTTP/3 addon is always HTTP/2 with zero QUIC probing
|
|
9817
|
+
* either way - see http3-transport.ts.
|
|
9818
|
+
*
|
|
9819
|
+
* Why HTTP/2 is the default rather than the race: on a cold burst the race
|
|
9820
|
+
* costs several times what HTTP/2 does. The promotion to HTTP/3 is decided
|
|
9821
|
+
* by address 0's *connection* being ready, while every request for that host
|
|
9822
|
+
* is then spread over all of its sessions, so a burst is dispatched onto
|
|
9823
|
+
* HTTP/3 sessions that have not carried a request yet. Measured on one region
|
|
9824
|
+
* host at c=100, alternating order, three runs each: TTI p50 203 / 221 / 267 ms
|
|
9825
|
+
* on the race against 51 / 53 / 50 ms on HTTP/2 at 4 sessions per address, and
|
|
9826
|
+
* 28 / 55 / 235 / 250 ms against 43 / 57 / 52 / 66 ms at the default 8. Once the
|
|
9827
|
+
* pool is genuinely warm HTTP/3 is the faster of the two, so it stays available
|
|
9828
|
+
* for callers who can pre-warm it; it is just not a safe default for the first
|
|
9829
|
+
* burst, and a first burst is what a latency benchmark measures.
|
|
9669
9830
|
*/
|
|
9670
9831
|
|
|
9671
9832
|
interface BestTransportOptions {
|
|
9672
9833
|
http2?: Http2TransportOptions;
|
|
9673
9834
|
http3?: Http3TransportOptions;
|
|
9835
|
+
/**
|
|
9836
|
+
* Race HTTP/3 against HTTP/2 per region host. Default false, for the reason
|
|
9837
|
+
* in this module's doc comment. HTTP/3 still only ever promotes a host for
|
|
9838
|
+
* *future* requests, so opting in never delays a request in flight.
|
|
9839
|
+
*/
|
|
9840
|
+
raceHttp3?: boolean | undefined;
|
|
9674
9841
|
}
|
|
9675
9842
|
interface BestTransportResult {
|
|
9676
9843
|
transport: RunnerTransport;
|
|
@@ -9766,6 +9933,14 @@ declare class RunnerError extends Error {
|
|
|
9766
9933
|
* two carries it.
|
|
9767
9934
|
*/
|
|
9768
9935
|
get isBusy(): boolean;
|
|
9936
|
+
/**
|
|
9937
|
+
* `429 rate_limited`: the key's own window on this runner has no room.
|
|
9938
|
+
*
|
|
9939
|
+
* Separate from `isBusy`, which means this runner's admission is full for
|
|
9940
|
+
* everyone. The limiter counts per key per runner, so a refusal here says
|
|
9941
|
+
* nothing about the next address, and `createSandbox` may try that one.
|
|
9942
|
+
*/
|
|
9943
|
+
get isRateLimited(): boolean;
|
|
9769
9944
|
/** C2: the runner doesn't serve this create shape at all - send it to api.miosa.ai instead. */
|
|
9770
9945
|
get isUnsupportedRequest(): boolean;
|
|
9771
9946
|
}
|