Repository navigation
Tags: meta/fbthrift
Tags
Write binary map keys as base64 when they are member names Summary: ## Context With `mapPrimitiveKeysAsMemberNames` on and `binaryAsBase64String` off, [[ https://www.internalfb.com/code/fbsource/fbcode/thrift/lib/cpp2/protocol/detail/Json5ProtocolWriter.cpp?lines=334-356 | Json5ProtocolWriter::writeBinary ]] wrote a binary map key as its raw bytes in the member name. [[ https://www.internalfb.com/code/fbsource/fbcode/thrift/lib/cpp2/protocol/detail/Json5ProtocolReader.cpp?lines=465-469 | Json5ProtocolReader::readBinaryValue ]] always decodes a member-name binary key as base64, so the writer's output did not read back. ## Behavior change Options: `mapPrimitiveKeysAsMemberNames` on, `binaryAsBase64String` off. **Now round-trips (silently corrupted before)** | Input | Field type | Before | After | | --- | --- | --- | --- | | `binaryAsKey = {"abcd": 1}` | `map<binary, i32>` | written as `{"binaryAsKey":{"abcd":1}}`, read back with key <69 B7 1D> | written as `{"binaryAsKey":{"YWJjZA":1}}`, read back with key `abcd` | **Now round-trips (failed before)** | Input | Field type | Before | After | | --- | --- | --- | --- | | `binaryAsKey = {"?~": 1}` | `map<binary, i32>` | written as `{"binaryAsKey":{"?~":1}}`, read rejected (not base64) | written as `{"binaryAsKey":{"P34":1}}`, read back with key `?~` | | `binaryAsKey = {<FF>: 1}` | `map<binary, i32>` | write rejected (not UTF-8) | written as `{"binaryAsKey":{"/w":1}}`, read back with key <FF> | **Unchanged** | Input | Options | Before | After | | --- | --- | --- | --- | | `binaryAsKey = {"?~": 1}` | `mapPrimitiveKeysAsMemberNames` and `binaryAsBase64String` on | `{"binaryAsKey":{"P34":1}}` | `{"binaryAsKey":{"P34":1}}` | | `binaryAsKey = {"?~": 1}` | defaults | `{"binaryAsKey":[{"key":{"utf-8":"?~"},"value":1}]}` | `{"binaryAsKey":[{"key":{"utf-8":"?~"},"value":1}]}` | | `binaryValue = "?~"` | `mapPrimitiveKeysAsMemberNames` on | `{"binaryValue":{"utf-8":"?~"}}` | `{"binaryValue":{"utf-8":"?~"}}` | Every caller found in fbsource that enables `mapPrimitiveKeysAsMemberNames` also sets `binaryAsBase64String`, so their output does not change. ## In this Diff `writeBinary` now uses unpadded base64, the encoding `binaryAsBase64String` already uses, for any binary written as an object member name. A member name cannot hold the `{"utf-8": ...}` form that tells the reader how a binary value is encoded, so base64 is the only form the reader can decode there. ___ landed-with-radar-review Differential Revision: D127514962 fbshipit-source-id: 91fab09964ec146f230b6ab3cb65004091e40330
Attribute stream flow-control wait time Summary: # Summary **TL;DR:** Attribute Thrift stream flow-control waits to the wall-time profiler and expose their duration in per-service Thrift dynostats. **Rule:** Low-level async I/O waits must end their `WallTimeOperation` and record the resulting I/O duration in the corresponding profiling counter. --- ## Context `ThriftProcessorBase::genStream` waits for client stream credits through `$server_stream->genIsStreamReady()`. Without a `WallTimeOperation`, the wall-time profiler cannot attribute that external-thread-event wait and reports `UnattributedIOTimeException`. This surfaced when Nest GraphQL-over-Thrift streaming traffic increased, producing roughly 20k profiling-completeness violations per day. - Task: T290256140 - MID: [opes/6ad7eca509ccfc81c34edbbc345195bc](http://www.internalfb.com/logview/opes/6ad7eca509ccfc81c34edbbc345195bc) ## This diff - Wrap the `genIsStreamReady()` await in a `WallTimeOperation` with `try`/`finally` so the operation always ends, including cancellation and exception paths. - Record the wait as `ProfilingCounterDuration::THRIFT_READ_DURATION` using `getOldestRunningIODuration()`. - Attribute the dynostats duration to `static::THRIFT_SVC_NAME` for per-service visibility. Reviewed By: jano Differential Revision: D122232086 fbshipit-source-id: 5ef07ce26a7706846999609ccd1011d4fb1b62f4
Propagate explicitly tagged Bronze/Sheddable RequestPriority to allow… …listed downstreams Summary: Adds `RequestPriorityContextHandler`, a ContextProp V2 `IContextHandler` that writes www's effective request priority onto the outgoing `ThriftFrameworkMetadata.request_priority` for allowlisted downstream services. Multifeed aggregator tiers are the first target. Behavior in `onOutgoingDownstream()`: - Effective priority = `MCPContext::getRequestPriority()`: AdmissionControl's resolved priority, the same value used for throttling. Every tagger (PrivacyLib, OUC tiers, Falco, GraphQL2, FAM ads) goes through `AdmissionControl::genCheck` and stores the admitted priority in implicit context, scoped to that request or function call tree, so concurrent branches outside an OUC scope are unaffected. Deliberately not read: the request-global `ThriftContextPropState` (S715712 leak source) and `PrivacyLibRequestPriorityState` (request-global and last-writer-wins across concurrent PrivacyLib executions, so code outside any IC scope could pick up another branch's Bronze). Code outside IC scope sends NULL. - Only `SHEDDABLE_PLUS` (Bronze) and `SHEDDABLE` are ever written. Untagged traffic and `CRITICAL`/`CRITICAL_PLUS` keep sending a null priority. This avoids the S640167 failure mode (see D98537289), where writing the default `CRITICAL` for all traffic activated dormant downgrade logic downstream. - Gated by the existing JK `www/web_efficiency_infra:pl_set_priority_to_tcp`, evaluated with switchval = SR `service_name` (per-destination allowlist; default false) and hashval = request id (% ramp). This knob originally gated the removed PrivacyLib TCP setter and has no other readers. - Never upgrades: if the TFM already carries a more sheddable upstream priority, that value is kept. - Only mutates the per-call TFM copy built by `TContextPropV2ClientHandler`. The global `ThriftContextPropState` is untouched, so in-process readers (MAPI/AM priority handlers, ADAL, Galileo request utils) see no change, and concurrent calls cannot inherit a scoped priority (S715712). Per-client floors such as `IGAdsDjangoCallCriticalPriorityContextHandler` (D123515309) are attached after this handler and still win. Registered in `ThriftContextPropHandlers::install()` next to `ProductIdContextHandler`, behind the killswitch `upop/contextprop_priority:disable_request_priority_context_handler` (default false). That covers every SR Thrift client: `servicerouter/thrift_context_prop:enabled` is fully on. Context: "ContextProp: From Web to Downstream" doc (https://docs.google.com/document/d/1PJWKXE8MxarX09WMH621kDojLkmJSQguN1arXcskpxo). Reviewed By: DavidLouie Differential Revision: D123739942 fbshipit-source-id: 4234e8443b715184d39fc86ead75fa63dc0962cd
Update recommended HTTP headers Summary: Updates the generated common-header files. Diff resulted from pipeline (D115638777) and is first in plan to generate a monthly bot to update the common headers lists. Diff consists of updates to the headers list files, and resulting build errors from callers of it. In HTTPCommonHeaders.txt: Added 4 headers, removed 16 In FacebookHTTPHeaders.txt: Added 63 Headers, removed 51 The net total between the two lists stayed as 254 headers. For details on the decision of how headers were chosen to be removed this diff explains (D115508426), but tldr is: - Headers counts were aggregated (1/10^6 sampling) to a scuba table - Through the actual count of each header itself, the tiers each header appearance occurred on (slightly more value for edge and fna tiers), and the amount a header enum appears in code (for listed headers), a score was assigned to each header (higher score -> more valuable) - The scores were sorted such that if [highest scored non-list header / lowest scored listed header] was greater than a certain ratio (chose 2.0 for first run), the header would replace it on the list - This kept going until all of the non-listed headers were checked with the lowest scored non-swapped listed headers Additionally: Theres a DENY_LIST for headers that likely shouldn't be removed (some psuedoheaders, connection headers, etc...) and for headers used more than 50 times in code as I deemed that traffic over a few weeks period of time likely isn't enough to justify removing them. If you believe that a header was removed that you don't think should be removed from the list or if you believe anything gets broken from this change please lmk. But advantages of this change can be seen below in the test plan when testing on different canary teirs. Reviewed By: hanidamlaj Differential Revision: D116961031 fbshipit-source-id: 9d6c281ba22ed3732fddb3f860527deb20f756fa
Move instead of copy message temporary in TLibraryException constructor Reviewed By: cnli87 Differential Revision: D122056416 fbshipit-source-id: 7258dfdfe6f32caf1441ede59350bc2d625931ae
Revert D120720989: Keep TStructDataStorage members out of writable .r… …odata Differential Revision: D120720989 Original commit changeset: 4fbbf6c47a56 Original Phabricator Diff: D120720989 fbshipit-source-id: 65c5292a840dc474da280c93fc9c4671a50b2ae1
Updating hashes Summary: GitHub commits: WhatsApp/erlang-language-platform@8ecd7f2 meta/CacheLib@92944e5 meta/fb303@48b10d7 a78dbc9 meta/folly@7bfa034 meta/mvfst@c956401 meta/proxygen@d79b298 meta/pyrefly@be0f564 meta/wangle@a124f43 facebookexperimental/edencommon@fd11084 facebookexperimental/rust-shed@dd4e0bb facebookincubator/fizz@0931563 Reviewed By: ajb85 fbshipit-source-id: 2dc685869299b73ad437e8d34bcb3a7bcf734f64
Expose the application adapter factory Summary: Expose the application adapter factory registered with `FastThriftServer`, mirroring classic `ThriftServer::getProcessorFactory()`. This lets pre-start integrations consume the generated service metadata and schema without including auxiliary interfaces or enabling the wire metadata service. ___ Differential Revision: D119040039 fbshipit-source-id: 2261ee4a6692ebe435d29c9a75d41638a6c93044
Deprecate ChainInterceptors Summary: Mark ChainInterceptors as deprecated and direct callers to the modern ServiceInterceptor API. Reviewed By: adolfojunior Differential Revision: D117902588 fbshipit-source-id: 18f569dc1f02deacf7c924c56901ef8b2944d0f9
Carry the per-connection and per-request internal fields Summary: Gives `ThriftConnContext` and `ThriftRequestContext` the `getInternalFields<T>()` slot the classic contexts carry, over fast_thrift's own `TypeErasedValue<128>` and pluggable functions rather than a dependency on `Cpp2ConnContext`. Reviewed By: robertroeser Differential Revision: D116839752 fbshipit-source-id: e7f5da7ae639c2b7a3e20c8b275adc18e323820c
PreviousNext