Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: prevent eventstream errors on shutdown or client aborts #5784

Merged
merged 1 commit into from
Jul 21, 2023

Conversation

nflaig
Copy link
Member

@nflaig nflaig commented Jul 21, 2023

Motivation

Closes #5783

Description

Before writing to the .raw stream it is recommended to call .hijack, see fastify/fastify#3979 (comment).
This prevents Fastify from sending the response and avoids "Error: Cannot set headers after they are sent to the client" errors during shutdown or client aborts.

See mention of .hijack() in Lifecycle.md. Further details can be found in Reply.md#hijack

The previous changes done in #5722 and changes of this PR will fix all the errors reported in #5323. We might consider closing this issue as well after checking with user that reported it.

@nflaig nflaig requested a review from a team as a code owner July 21, 2023 15:12
@github-actions
Copy link
Contributor

github-actions bot commented Jul 21, 2023

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: f52cb8c Previous: 03c36e2 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 621.87 us/op 587.67 us/op 1.06
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 71.425 us/op 75.578 us/op 0.95
BLS verify - blst-native 1.1509 ms/op 1.2456 ms/op 0.92
BLS verifyMultipleSignatures 3 - blst-native 2.3363 ms/op 2.5333 ms/op 0.92
BLS verifyMultipleSignatures 8 - blst-native 5.0258 ms/op 5.4419 ms/op 0.92
BLS verifyMultipleSignatures 32 - blst-native 18.117 ms/op 19.685 ms/op 0.92
BLS aggregatePubkeys 32 - blst-native 24.003 us/op 26.044 us/op 0.92
BLS aggregatePubkeys 128 - blst-native 94.436 us/op 101.81 us/op 0.93
getAttestationsForBlock 47.018 ms/op 55.591 ms/op 0.85
isKnown best case - 1 super set check 253.00 ns/op 282.00 ns/op 0.90
isKnown normal case - 2 super set checks 250.00 ns/op 279.00 ns/op 0.90
isKnown worse case - 16 super set checks 250.00 ns/op 269.00 ns/op 0.93
CheckpointStateCache - add get delete 4.6330 us/op 5.1100 us/op 0.91
validate api signedAggregateAndProof - struct 2.6689 ms/op 2.7456 ms/op 0.97
validate gossip signedAggregateAndProof - struct 2.6735 ms/op 2.7539 ms/op 0.97
validate api attestation - struct 1.3105 ms/op 1.2994 ms/op 1.01
validate gossip attestation - struct 1.3191 ms/op 1.3201 ms/op 1.00
pickEth1Vote - no votes 1.1646 ms/op 1.2100 ms/op 0.96
pickEth1Vote - max votes 10.573 ms/op 9.1821 ms/op 1.15
pickEth1Vote - Eth1Data hashTreeRoot value x2048 8.6152 ms/op 8.7640 ms/op 0.98
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 13.029 ms/op 13.661 ms/op 0.95
pickEth1Vote - Eth1Data fastSerialize value x2048 546.42 us/op 577.03 us/op 0.95
pickEth1Vote - Eth1Data fastSerialize tree x2048 5.7438 ms/op 4.1162 ms/op 1.40
bytes32 toHexString 458.00 ns/op 477.00 ns/op 0.96
bytes32 Buffer.toString(hex) 276.00 ns/op 290.00 ns/op 0.95
bytes32 Buffer.toString(hex) from Uint8Array 416.00 ns/op 424.00 ns/op 0.98
bytes32 Buffer.toString(hex) + 0x 274.00 ns/op 287.00 ns/op 0.95
Object access 1 prop 0.15300 ns/op 0.15600 ns/op 0.98
Map access 1 prop 0.14400 ns/op 0.14100 ns/op 1.02
Object get x1000 6.8860 ns/op 6.7280 ns/op 1.02
Map get x1000 0.49000 ns/op 0.57600 ns/op 0.85
Object set x1000 46.537 ns/op 46.605 ns/op 1.00
Map set x1000 37.483 ns/op 36.943 ns/op 1.01
Return object 10000 times 0.23920 ns/op 0.22810 ns/op 1.05
Throw Error 10000 times 3.7996 us/op 3.8855 us/op 0.98
fastMsgIdFn sha256 / 200 bytes 3.1620 us/op 3.2230 us/op 0.98
fastMsgIdFn h32 xxhash / 200 bytes 288.00 ns/op 272.00 ns/op 1.06
fastMsgIdFn h64 xxhash / 200 bytes 340.00 ns/op 331.00 ns/op 1.03
fastMsgIdFn sha256 / 1000 bytes 10.959 us/op 11.075 us/op 0.99
fastMsgIdFn h32 xxhash / 1000 bytes 412.00 ns/op 397.00 ns/op 1.04
fastMsgIdFn h64 xxhash / 1000 bytes 416.00 ns/op 422.00 ns/op 0.99
fastMsgIdFn sha256 / 10000 bytes 99.737 us/op 104.36 us/op 0.96
fastMsgIdFn h32 xxhash / 10000 bytes 1.8240 us/op 1.9240 us/op 0.95
fastMsgIdFn h64 xxhash / 10000 bytes 1.2460 us/op 1.3170 us/op 0.95
enrSubnets - fastDeserialize 64 bits 1.1790 us/op 1.2500 us/op 0.94
enrSubnets - ssz BitVector 64 bits 412.00 ns/op 435.00 ns/op 0.95
enrSubnets - fastDeserialize 4 bits 163.00 ns/op 169.00 ns/op 0.96
enrSubnets - ssz BitVector 4 bits 407.00 ns/op 445.00 ns/op 0.91
prioritizePeers score -10:0 att 32-0.1 sync 2-0 95.308 us/op 101.27 us/op 0.94
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 115.53 us/op 132.43 us/op 0.87
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 150.91 us/op 179.36 us/op 0.84
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 273.45 us/op 295.09 us/op 0.93
prioritizePeers score 0:0 att 64-1 sync 4-1 323.32 us/op 361.15 us/op 0.90
array of 16000 items push then shift 1.5181 us/op 1.6209 us/op 0.94
LinkedList of 16000 items push then shift 8.6040 ns/op 9.0220 ns/op 0.95
array of 16000 items push then pop 54.435 ns/op 57.340 ns/op 0.95
LinkedList of 16000 items push then pop 8.5720 ns/op 8.8980 ns/op 0.96
array of 24000 items push then shift 2.3117 us/op 2.4255 us/op 0.95
LinkedList of 24000 items push then shift 8.6110 ns/op 9.2620 ns/op 0.93
array of 24000 items push then pop 96.244 ns/op 115.38 ns/op 0.83
LinkedList of 24000 items push then pop 8.3900 ns/op 8.7210 ns/op 0.96
intersect bitArray bitLen 8 6.6580 ns/op 6.9630 ns/op 0.96
intersect array and set length 8 55.671 ns/op 61.077 ns/op 0.91
intersect bitArray bitLen 128 30.915 ns/op 32.238 ns/op 0.96
intersect array and set length 128 746.49 ns/op 795.41 ns/op 0.94
bitArray.getTrueBitIndexes() bitLen 128 1.3750 us/op 1.4730 us/op 0.93
bitArray.getTrueBitIndexes() bitLen 248 2.2870 us/op 2.5500 us/op 0.90
bitArray.getTrueBitIndexes() bitLen 512 4.5780 us/op 4.9330 us/op 0.93
Buffer.concat 32 items 1.0320 us/op 1.0820 us/op 0.95
Uint8Array.set 32 items 2.3310 us/op 1.6930 us/op 1.38
transfer serialized Status (84 B) 1.9070 us/op 1.8930 us/op 1.01
copy serialized Status (84 B) 1.5750 us/op 1.5580 us/op 1.01
transfer serialized SignedVoluntaryExit (112 B) 2.0710 us/op 1.9990 us/op 1.04
copy serialized SignedVoluntaryExit (112 B) 1.7450 us/op 1.6820 us/op 1.04
transfer serialized ProposerSlashing (416 B) 2.9170 us/op 2.2390 us/op 1.30
copy serialized ProposerSlashing (416 B) 2.7110 us/op 1.9910 us/op 1.36
transfer serialized Attestation (485 B) 2.5320 us/op 2.2600 us/op 1.12
copy serialized Attestation (485 B) 2.7280 us/op 1.9570 us/op 1.39
transfer serialized AttesterSlashing (33232 B) 2.4620 us/op 2.3190 us/op 1.06
copy serialized AttesterSlashing (33232 B) 4.8100 us/op 5.3140 us/op 0.91
transfer serialized Small SignedBeaconBlock (128000 B) 2.7420 us/op 2.5530 us/op 1.07
copy serialized Small SignedBeaconBlock (128000 B) 12.535 us/op 13.212 us/op 0.95
transfer serialized Avg SignedBeaconBlock (200000 B) 2.9570 us/op 2.8830 us/op 1.03
copy serialized Avg SignedBeaconBlock (200000 B) 17.910 us/op 19.369 us/op 0.92
transfer serialized BlobsSidecar (524380 B) 2.7210 us/op 3.0670 us/op 0.89
copy serialized BlobsSidecar (524380 B) 92.589 us/op 85.813 us/op 1.08
transfer serialized Big SignedBeaconBlock (1000000 B) 2.8680 us/op 2.9630 us/op 0.97
copy serialized Big SignedBeaconBlock (1000000 B) 147.34 us/op 172.81 us/op 0.85
pass gossip attestations to forkchoice per slot 2.1149 ms/op 2.1509 ms/op 0.98
forkChoice updateHead vc 100000 bc 64 eq 0 2.1050 ms/op 2.1502 ms/op 0.98
forkChoice updateHead vc 600000 bc 64 eq 0 11.671 ms/op 13.857 ms/op 0.84
forkChoice updateHead vc 1000000 bc 64 eq 0 18.019 ms/op 22.681 ms/op 0.79
forkChoice updateHead vc 600000 bc 320 eq 0 16.734 ms/op 17.422 ms/op 0.96
forkChoice updateHead vc 600000 bc 1200 eq 0 81.035 ms/op 83.512 ms/op 0.97
forkChoice updateHead vc 600000 bc 64 eq 1000 18.906 ms/op 22.438 ms/op 0.84
forkChoice updateHead vc 600000 bc 64 eq 10000 20.764 ms/op 24.881 ms/op 0.83
forkChoice updateHead vc 600000 bc 64 eq 300000 27.288 ms/op 34.033 ms/op 0.80
computeDeltas 3.2544 ms/op 3.0862 ms/op 1.05
computeProposerBoostScoreFromBalances 365.92 us/op 386.09 us/op 0.95
altair processAttestation - 250000 vs - 7PWei normalcase 1.8997 ms/op 2.1128 ms/op 0.90
altair processAttestation - 250000 vs - 7PWei worstcase 3.0808 ms/op 3.5394 ms/op 0.87
altair processAttestation - setStatus - 1/6 committees join 172.27 us/op 179.82 us/op 0.96
altair processAttestation - setStatus - 1/3 committees join 335.72 us/op 365.63 us/op 0.92
altair processAttestation - setStatus - 1/2 committees join 440.55 us/op 482.94 us/op 0.91
altair processAttestation - setStatus - 2/3 committees join 572.88 us/op 600.47 us/op 0.95
altair processAttestation - setStatus - 4/5 committees join 770.07 us/op 816.59 us/op 0.94
altair processAttestation - setStatus - 100% committees join 916.04 us/op 959.49 us/op 0.95
altair processBlock - 250000 vs - 7PWei normalcase 9.7957 ms/op 9.5024 ms/op 1.03
altair processBlock - 250000 vs - 7PWei normalcase hashState 16.578 ms/op 17.223 ms/op 0.96
altair processBlock - 250000 vs - 7PWei worstcase 36.296 ms/op 37.231 ms/op 0.97
altair processBlock - 250000 vs - 7PWei worstcase hashState 57.987 ms/op 58.809 ms/op 0.99
phase0 processBlock - 250000 vs - 7PWei normalcase 2.6097 ms/op 2.2497 ms/op 1.16
phase0 processBlock - 250000 vs - 7PWei worstcase 28.058 ms/op 30.972 ms/op 0.91
altair processEth1Data - 250000 vs - 7PWei normalcase 476.11 us/op 455.55 us/op 1.05
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 9.8910 us/op 10.610 us/op 0.93
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 33.840 us/op 67.007 us/op 0.51
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 15.932 us/op 14.702 us/op 1.08
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 11.483 us/op 16.489 us/op 0.70
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 120.96 us/op 206.03 us/op 0.59
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.3101 ms/op 1.3837 ms/op 0.95
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.7846 ms/op 1.6070 ms/op 1.11
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.4323 ms/op 1.8318 ms/op 0.78
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.3240 ms/op 3.7942 ms/op 0.88
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.2861 ms/op 2.7579 ms/op 0.83
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.8289 ms/op 5.4350 ms/op 0.89
Tree 40 250000 create 332.72 ms/op 313.58 ms/op 1.06
Tree 40 250000 get(125000) 199.22 ns/op 199.26 ns/op 1.00
Tree 40 250000 set(125000) 966.86 ns/op 887.69 ns/op 1.09
Tree 40 250000 toArray() 18.141 ms/op 18.635 ms/op 0.97
Tree 40 250000 iterate all - toArray() + loop 17.927 ms/op 22.368 ms/op 0.80
Tree 40 250000 iterate all - get(i) 68.304 ms/op 73.888 ms/op 0.92
MutableVector 250000 create 11.657 ms/op 13.485 ms/op 0.86
MutableVector 250000 get(125000) 6.3140 ns/op 6.6350 ns/op 0.95
MutableVector 250000 set(125000) 235.68 ns/op 292.64 ns/op 0.81
MutableVector 250000 toArray() 2.9119 ms/op 3.8601 ms/op 0.75
MutableVector 250000 iterate all - toArray() + loop 2.8454 ms/op 4.1596 ms/op 0.68
MutableVector 250000 iterate all - get(i) 1.4747 ms/op 1.5896 ms/op 0.93
Array 250000 create 2.6101 ms/op 3.7404 ms/op 0.70
Array 250000 clone - spread 1.0461 ms/op 1.2828 ms/op 0.82
Array 250000 get(125000) 0.50100 ns/op 0.64500 ns/op 0.78
Array 250000 set(125000) 0.57200 ns/op 0.69500 ns/op 0.82
Array 250000 iterate all - loop 77.968 us/op 115.07 us/op 0.68
effectiveBalanceIncrements clone Uint8Array 300000 22.247 us/op 49.006 us/op 0.45
effectiveBalanceIncrements clone MutableVector 300000 283.00 ns/op 449.00 ns/op 0.63
effectiveBalanceIncrements rw all Uint8Array 300000 170.75 us/op 193.07 us/op 0.88
effectiveBalanceIncrements rw all MutableVector 300000 73.930 ms/op 109.22 ms/op 0.68
phase0 afterProcessEpoch - 250000 vs - 7PWei 107.01 ms/op 123.00 ms/op 0.87
phase0 beforeProcessEpoch - 250000 vs - 7PWei 37.033 ms/op 42.831 ms/op 0.86
altair processEpoch - mainnet_e81889 311.12 ms/op 382.46 ms/op 0.81
mainnet_e81889 - altair beforeProcessEpoch 48.153 ms/op 80.787 ms/op 0.60
mainnet_e81889 - altair processJustificationAndFinalization 12.915 us/op 28.293 us/op 0.46
mainnet_e81889 - altair processInactivityUpdates 5.2607 ms/op 7.4108 ms/op 0.71
mainnet_e81889 - altair processRewardsAndPenalties 68.774 ms/op 69.301 ms/op 0.99
mainnet_e81889 - altair processRegistryUpdates 2.1930 us/op 3.5210 us/op 0.62
mainnet_e81889 - altair processSlashings 436.00 ns/op 618.00 ns/op 0.71
mainnet_e81889 - altair processEth1DataReset 501.00 ns/op 816.00 ns/op 0.61
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.2510 ms/op 1.4402 ms/op 0.87
mainnet_e81889 - altair processSlashingsReset 2.7230 us/op 3.9150 us/op 0.70
mainnet_e81889 - altair processRandaoMixesReset 3.8260 us/op 11.201 us/op 0.34
mainnet_e81889 - altair processHistoricalRootsUpdate 658.00 ns/op 1.9950 us/op 0.33
mainnet_e81889 - altair processParticipationFlagUpdates 1.8250 us/op 2.9620 us/op 0.62
mainnet_e81889 - altair processSyncCommitteeUpdates 1.2280 us/op 1.3840 us/op 0.89
mainnet_e81889 - altair afterProcessEpoch 125.10 ms/op 136.98 ms/op 0.91
phase0 processEpoch - mainnet_e58758 349.78 ms/op 396.65 ms/op 0.88
mainnet_e58758 - phase0 beforeProcessEpoch 135.90 ms/op 156.37 ms/op 0.87
mainnet_e58758 - phase0 processJustificationAndFinalization 13.086 us/op 18.192 us/op 0.72
mainnet_e58758 - phase0 processRewardsAndPenalties 67.818 ms/op 70.941 ms/op 0.96
mainnet_e58758 - phase0 processRegistryUpdates 10.500 us/op 14.701 us/op 0.71
mainnet_e58758 - phase0 processSlashings 502.00 ns/op 685.00 ns/op 0.73
mainnet_e58758 - phase0 processEth1DataReset 402.00 ns/op 583.00 ns/op 0.69
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.3310 ms/op 2.1037 ms/op 0.63
mainnet_e58758 - phase0 processSlashingsReset 2.1460 us/op 2.3930 us/op 0.90
mainnet_e58758 - phase0 processRandaoMixesReset 3.8870 us/op 4.1330 us/op 0.94
mainnet_e58758 - phase0 processHistoricalRootsUpdate 500.00 ns/op 545.00 ns/op 0.92
mainnet_e58758 - phase0 processParticipationRecordUpdates 3.5570 us/op 3.9680 us/op 0.90
mainnet_e58758 - phase0 afterProcessEpoch 93.861 ms/op 102.80 ms/op 0.91
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.2057 ms/op 1.2775 ms/op 0.94
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.4851 ms/op 1.4495 ms/op 1.02
altair processInactivityUpdates - 250000 normalcase 22.742 ms/op 26.473 ms/op 0.86
altair processInactivityUpdates - 250000 worstcase 23.749 ms/op 28.869 ms/op 0.82
phase0 processRegistryUpdates - 250000 normalcase 9.6100 us/op 11.279 us/op 0.85
phase0 processRegistryUpdates - 250000 badcase_full_deposits 313.84 us/op 388.64 us/op 0.81
phase0 processRegistryUpdates - 250000 worstcase 0.5 127.37 ms/op 145.18 ms/op 0.88
altair processRewardsAndPenalties - 250000 normalcase 74.645 ms/op 72.579 ms/op 1.03
altair processRewardsAndPenalties - 250000 worstcase 73.023 ms/op 71.990 ms/op 1.01
phase0 getAttestationDeltas - 250000 normalcase 7.8541 ms/op 7.7880 ms/op 1.01
phase0 getAttestationDeltas - 250000 worstcase 7.6121 ms/op 9.1618 ms/op 0.83
phase0 processSlashings - 250000 worstcase 2.1903 ms/op 2.3777 ms/op 0.92
altair processSyncCommitteeUpdates - 250000 146.71 ms/op 154.86 ms/op 0.95
BeaconState.hashTreeRoot - No change 266.00 ns/op 270.00 ns/op 0.99
BeaconState.hashTreeRoot - 1 full validator 50.235 us/op 53.301 us/op 0.94
BeaconState.hashTreeRoot - 32 full validator 495.80 us/op 566.47 us/op 0.88
BeaconState.hashTreeRoot - 512 full validator 5.1146 ms/op 6.0259 ms/op 0.85
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 63.392 us/op 82.538 us/op 0.77
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 831.19 us/op 1.1791 ms/op 0.70
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 11.214 ms/op 15.435 ms/op 0.73
BeaconState.hashTreeRoot - 1 balances 48.318 us/op 59.557 us/op 0.81
BeaconState.hashTreeRoot - 32 balances 456.51 us/op 599.41 us/op 0.76
BeaconState.hashTreeRoot - 512 balances 4.3600 ms/op 5.4677 ms/op 0.80
BeaconState.hashTreeRoot - 250000 balances 75.035 ms/op 85.910 ms/op 0.87
aggregationBits - 2048 els - zipIndexesInBitList 15.027 us/op 22.740 us/op 0.66
regular array get 100000 times 32.030 us/op 37.414 us/op 0.86
wrappedArray get 100000 times 31.929 us/op 37.659 us/op 0.85
arrayWithProxy get 100000 times 15.343 ms/op 16.529 ms/op 0.93
ssz.Root.equals 220.00 ns/op 278.00 ns/op 0.79
byteArrayEquals 211.00 ns/op 306.00 ns/op 0.69
shuffle list - 16384 els 7.0655 ms/op 7.6951 ms/op 0.92
shuffle list - 250000 els 101.46 ms/op 118.01 ms/op 0.86
processSlot - 1 slots 8.1850 us/op 11.740 us/op 0.70
processSlot - 32 slots 1.3213 ms/op 1.6169 ms/op 0.82
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 56.374 ms/op 67.336 ms/op 0.84
getCommitteeAssignments - req 1 vs - 250000 vc 2.4839 ms/op 2.8179 ms/op 0.88
getCommitteeAssignments - req 100 vs - 250000 vc 3.6781 ms/op 4.2982 ms/op 0.86
getCommitteeAssignments - req 1000 vs - 250000 vc 4.0043 ms/op 4.8622 ms/op 0.82
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.8900 ns/op 5.9800 ns/op 0.82
state getBlockRootAtSlot - 250000 vs - 7PWei 495.80 ns/op 831.87 ns/op 0.60
computeProposers - vc 250000 8.5452 ms/op 11.285 ms/op 0.76
computeEpochShuffling - vc 250000 103.30 ms/op 137.55 ms/op 0.75
getNextSyncCommittee - vc 250000 145.05 ms/op 213.51 ms/op 0.68
computeSigningRoot for AttestationData 12.539 us/op 14.413 us/op 0.87
hash AttestationData serialized data then Buffer.toString(base64) 2.1806 us/op 2.4253 us/op 0.90
toHexString serialized data 1.0389 us/op 1.1851 us/op 0.88
Buffer.toString(base64) 209.75 ns/op 246.84 ns/op 0.85

by benchmarkbot/action

@nflaig nflaig force-pushed the nflaig/fix-cannot-set-headers branch 3 times, most recently from b53faa9 to 8239979 Compare July 21, 2023 17:15
@nflaig nflaig changed the title fix: check if response is writable before sending SSE event fix: prevent eventstream errors on shutdown or abrupt client aborts Jul 21, 2023
@nflaig nflaig changed the title fix: prevent eventstream errors on shutdown or abrupt client aborts fix: prevent eventstream errors on shutdown or client aborts Jul 21, 2023
@nflaig nflaig force-pushed the nflaig/fix-cannot-set-headers branch from 8239979 to 905c4b9 Compare July 21, 2023 17:24
@@ -37,9 +43,6 @@ export function getRoutes(config: ChainForkConfig, api: ServerApi<Api>): ServerR
await new Promise<void>((resolve, reject) => {
void api.eventstream(req.query.topics, controller.signal, (event) => {
try {
// If the request is already aborted, we don't need to send any more events.
if (req.raw.destroyed) return;
Copy link
Member Author

@nflaig nflaig Jul 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as it did not resolve the issue (added in #5722)

// Prevent Fastify from sending the response, this is recommended before writing to the `.raw` stream
// and avoids "Cannot set headers after they are sent to the client" errors during shutdown or abrupt client aborts.
// See https://github.com/fastify/fastify/issues/3979, https://github.com/ChainSafe/lodestar/issues/5783
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hijack() is not async, see reply.js#L116

@nflaig nflaig force-pushed the nflaig/fix-cannot-set-headers branch from 905c4b9 to 24843a6 Compare July 21, 2023 18:33
Copy link
Contributor

@nazarhussain nazarhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems very tricky, but as per the referenced issue it seems to works.

@nflaig nflaig merged commit 3257345 into unstable Jul 21, 2023
12 checks passed
@nflaig nflaig deleted the nflaig/fix-cannot-set-headers branch July 21, 2023 21:16
@nflaig
Copy link
Member Author

nflaig commented Jul 22, 2023

I researched a bit more to make sure "hijacking" the response (res.hijack()) does not have any negative side-effects in our case.
Found a great article that mentions a few risks.

The most important consideration is about not execution hooks in our case as closing the evenstream api via res.raw.end() does not do anything, the socket has to be force closed on the server unless client closes it.

There are custom hooks that are skipped now, namely onResponse (which was never executed anyhow) and onError which just created noise before by logging error: Req req-5 eventstream error aborted (not a helpful/relevant error). Once the connection is established, the server-sent events do not throw any errors. There is a bug currently when validating topics as this error is never returned to client and connection is just kept open but this will be fixed by #5787.

All other hooks are called before handler is invoked, meaning CORS headers are still set by plugin and onRequest hook is still executed as well.

@wemeetagain
Copy link
Member

🎉 This PR is included in v1.10.0 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Error: Cannot set headers after they are sent to the client
3 participants