今日已更新 80 条资讯 | 累计 20052 条内容
关于我们

标签:#cap

找到 17 篇相关文章

AI 资讯

Handling Lazy-Loaded Content in Automated Screenshots

You set up Puppeteer, navigate to a page, call page.screenshot() , and the bottom half of your image is blank placeholder boxes. Welcome to lazy loading. Most modern sites defer images and heavy content until the user scrolls. Your headless browser never scrolls. So those elements never load. Here's how to deal with it. The scroll trick The most common fix is to programmatically scroll down the page before taking the screenshot: async function scrollToBottom ( page ) { await page . evaluate ( async () => { const delay = ms => new Promise ( r => setTimeout ( r , ms )); const distance = 300 ; while ( window . scrollY + window . innerHeight < document . body . scrollHeight ) { window . scrollBy ( 0 , distance ); await delay ( 150 ); } window . scrollTo ( 0 , 0 ); }); } await page . goto ( " https://example.com " , { waitUntil : " networkidle2 " }); await scrollToBottom ( page ); await page . waitForTimeout ( 1000 ); await page . screenshot ({ fullPage : true }); The 150ms delay between scrolls gives IntersectionObserver -based lazy loaders time to trigger. Too fast and you'll scroll past elements before they start loading. That final waitForTimeout after scrolling back to top lets any remaining images finish rendering. Not elegant, but necessary. Why networkidle2 isn't enough You'd think waitUntil: "networkidle2" would handle this. It waits until there are no more than 2 network connections for 500ms. But lazy-loaded images haven't even been requested yet at that point — they're waiting for a scroll event that never happens. networkidle2 only helps with content that loads on page init. For scroll-triggered content, you need the scroll. The loading="eager" override Some sites use the native loading="lazy" attribute. You can override it before images load: await page . evaluateOnNewDocument (() => { Object . defineProperty ( HTMLImageElement . prototype , " loading " , { set : function ( val ) { this . setAttribute ( " loading " , " eager " ); }, get : function () { retu

2026-07-12 原文 →
AI 资讯

CAP Theorem — Consistency vs Availability

CAP: khi network partition xảy ra, chỉ được chọn C hoặc A — không có "cả ba" CAP theorem là kết quả của Gilbert và Lynch (formal proof năm 2002 cho conjecture Brewer đưa ra ở PODC keynote 2000): một hệ phân tán có shared state không thể đồng thời cung cấp cả linearizable Consistency , Availability (mọi request tới non-failing node đều trả lời không lỗi), và Partition tolerance khi có network partition. Trong thực tế, partition là thứ sẽ xảy ra — TCP retransmit, GC pause dài, switch chết, cross-region link flap — nên P là ràng buộc bắt buộc, không phải lựa chọn. Câu hỏi thật là: khi partition xảy ra, hệ thống hy sinh C hay A? Chọn sai gây ra hai loại incident khác nhau: chọn AP mà dữ liệu cần linearizable dẫn tới double-charge, oversell inventory, split-brain; chọn CP mà dữ liệu chỉ cần eventually consistent dẫn tới downtime không cần thiết, user không đọc được profile của chính mình. Cơ chế hoạt động Định nghĩa formal theo Gilbert và Lynch: Consistency ở đây là linearizability : mọi read sau một write hoàn tất phải thấy giá trị mới (hoặc mới hơn); tồn tại một total order các operation phù hợp với real-time. Availability : mọi request tới một non-failing node phải nhận response (không timeout, không error). Partition tolerance : hệ thống tiếp tục hoạt động dù network drop tuỳ ý message giữa các node. Proof intuition: giả sử có 2 node N1, N2 giữ cùng key x=0 . Client ghi x=1 vào N1. Link N1 và N2 đứt. Một client khác đọc x từ N2. Nếu N2 trả về 0 thì không linearizable (mất C). Nếu N2 chờ đến khi thấy được N1 thì mất A. Nếu N2 từ chối phục vụ thì cũng mất A. Không có cách thứ ba. Trong hệ CP, mỗi write phải qua quorum (Raft, Paxos, ZAB); khi node bị isolate khỏi quorum, nó từ chối phục vụ để giữ linearizability: // etcd/Raft-style: khi mất quorum, leader step down và write fail resp , err := kv . Put ( ctx , "order/42" , "paid" ) if err != nil { // err là ErrLeaderChanged hoặc context.DeadlineExceeded khi ở minority side // client thấy unavailable — đúng contract CP re

2026-07-08 原文 →
AI 资讯

Calculating On-Premises vs. Cloud Cost Break-Even for Small Businesses with Stable Workloads (5–7 Years)

Introduction: When Does On-Premises Outpace the Cloud? For small businesses like ComputeLabs , the decision between on-premises servers and cloud services isn’t just about cost—it’s about predictable stability versus elastic flexibility. With stable workloads (websites, email, file storage, backups, internal apps), the question narrows: Does a one-time server purchase amortized over 5–7 years beat monthly cloud bills? The answer hinges on a total cost of ownership (TCO) analysis , where upfront CAPEX collides with recurring OPEX , and hidden costs lurk in both models. The CAPEX vs. OPEX Tug-of-War On-premises servers demand a high initial investment —hardware, software licenses, setup. For a small business, this could mean $5,000–$15,000 upfront , depending on specs. Cloud services, in contrast, operate on a pay-as-you-go model , with monthly costs averaging $100–$500 for similar workloads. But here’s the catch: Cloud costs compound. Over 5 years, that’s $6,000–$30,000 —potentially double the on-premises CAPEX. The break-even point? When the cumulative cloud spend exceeds the depreciated server cost , typically 3–4 years in , assuming no major upgrades. Hidden Costs: The Silent Budget Killers On-premises servers aren’t just a one-time buy. Electricity (a 2U server consumes ~ 500W/hour , costing ~ $400/year ), cooling (fans degrade, heat expands components, shortening lifespan), and maintenance (disk failures, OS patches) add $500–$1,000/year. Cloud services mask these costs but introduce their own: data egress fees (AWS charges $0.09/GB for outbound transfers), premium support ( $100+/month ), and vendor lock-in (migrating data is costly). The edge case? Regulatory compliance —if data must stay on-premises, cloud costs become irrelevant, but self-managed security (firewalls, patches) becomes a non-negotiable expense. Scalability vs. Stability: The Workload Paradox Cloud’s elasticity is its strength—but for stable workloads, it’s overkill. An on-premises server sized

2026-07-06 原文 →
AI 资讯

Why your Cloudflare Turnstile token works in the browser but 403s from requests

Why your Cloudflare Turnstile token works in the browser but 403s from requests You solved the Turnstile widget. You can see the token in the page. You copy it into your script, POST the form from requests, and the server hands you back a 403 — or a JSON body with "success": false. The token clearly worked a second ago in the browser, so what changed? Short answer: a Turnstile token is not a password you can carry around. It's a one-time, short-lived proof bound to a very specific context, and replaying it from a different context is exactly what it's designed to reject. Below is what that context is, how to tell which constraint you're hitting, and the fix for each. The real scenario You're automating a flow on a Cloudflare-protected site. There's a cf-turnstile widget on the form. You get a token one of two ways: you render the page in a real browser (Playwright/Selenium) and read cf-turnstile-response, or you hand the sitekey + page URL to a solving service and get a token back. Either way, you then submit the form with a plain HTTP client requests, httpx, axios) and it fails. The frustrating part: it's intermittent-looking. The reason it feels random is that there are four separate constraints, and you're usually tripping a different one each time. The four things a Turnstile token is bound to 1. It's single-use Once Cloudflare validates a token server-side (the siteverify call your target makes), that token is spent. Submit twice, retry, or test it once by hand, and the second use returns false. You get a fresh one per submission. 2. It has a short TTL Turnstile tokens expire fast — a few minutes. Solve early, do other work, submit later, and the token can be dead on arrival. The widget auto-refreshes in the browser precisely because tokens go stale; a script that grabs the token and sits on it loses that refresh. 3. It's bound to the sitekey and the page URL Multiple widgets. Some pages embed more than one Turnstile (login + newsletter). Solving the wrong site

2026-06-28 原文 →
AI 资讯

Cloudflare Turnstile in Playwright: Why Your Tests Stall and How to Solve It in 8 Lines

Cloudflare Turnstile in Playwright: Why Your Tests Stall and How to Solve It in 8 Lines If you're running Playwright or Selenium against any site behind Cloudflare, you've already met Turnstile. It's the new "managed challenge" widget Cloudflare started shipping in 2023, and it now appears in front of login flows, contact forms, signup pages, and increasingly the entire site root. Here's the part most teams miss: Turnstile doesn't always show a checkbox. A lot of the time it just sits invisible, runs its scoring loop, and either issues a token silently or stalls forever. Your test doesn't crash. It just times out at the next page.click("button[type=submit]") . The CI log says "element not interactable." Nobody knows why. I work on CaptchaAI. I'm going to show you exactly what's happening, then drop in 8 lines that fix it. The real scenario You have a Playwright suite that runs every PR. One day a test starts failing on the signup flow. You re-run it. It fails again. Locally on your laptop it passes. On CI it doesn't. What's actually happening: Cloudflare flagged your CI runner's IP block (GitHub Actions, GitLab runners, Hetzner, OVH, DO — all of them are on Cloudflare's "elevated risk" list). Turnstile decides to switch from invisible mode to "managed challenge" mode. Now there's a widget in the DOM that needs a real token before the form submit will accept. Your test never interacted with the widget because last week it didn't exist. Why retries don't help The instinct is to add a retry: 2 and move on. Don't. Cloudflare's scoring is per-IP-per-fingerprint, and each retry from the same runner makes the next challenge harder, not easier. After ~3 attempts you'll get full block pages instead of the widget. The right move is to solve the widget once, inject the token, and submit normally — exactly what a human user does, just faster. How Turnstile actually issues a token The widget renders an iframe pointing at challenges.cloudflare.com . Inside the iframe it runs a fi

2026-06-04 原文 →