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

标签:#AR

找到 4337 篇相关文章

AI 资讯

What We Learned Rewriting an Interactive Map Editor: Fabric.js, CORS, and 20,000 Lines of Legacy TypeScript

A story about how migrating an interactive office map editor turned into an engineering investigation involving Fabric.js, tainted canvas , and an architecture that's finally easy to extend. In most software projects, one sentence usually makes every developer nervous: "Let's rewrite this module from scratch." It often means months of development, regression risks, and endless architecture discussions. Our project was no different. We develop, a workspace management platform that allows companies to manage office spaces and book desks. One of its core features is an interactive office map editor, where administrators upload floor plans, place desks and meeting rooms, and publish maps for employees. Over the years, this editor slowly evolved into a real monolith. And the problem wasn't simply the number of lines of code. Where It All Started The editor dated back to the AngularJS era. The main component had gradually grown into a single file responsible for almost everything: loading maps working with Fabric.js CRUD operations keyboard shortcuts dialogs saving event handling The main editor component alone contained nearly 2,270 lines of code . Behind it lived another codebase — the map engine itself. Almost 20,000 lines of TypeScript spread across more than 230 files. One of the biggest architectural issues was an infinite rendering loop. fabric . util . requestAnimFrame (() => this . tick ()); Even when the user wasn't interacting with the editor, rendering continued forever. It worked. But every new feature became more expensive to build. Why We Decided to Rewrite It The motivation wasn't AngularJS itself. The real reason was business requirements. The product needed completely new capabilities: map drafts safe publishing high-quality printing multiple workspace modes easier support for new object types Every new feature pushed harder against the existing architecture. Eventually it became obvious: We weren't fighting individual bugs anymore. We were fighting the

2026-07-08 原文 →
AI 资讯

Async Error Handling — Async Route

Async route: vì sao Promise reject trong Express 4 không tới error middleware, và cách Fastify tự bắt lỗi Một async route handler trông giống một handler bình thường, nhưng cơ chế truyền lỗi của nó khác hẳn. Express 4 bọc lời gọi handler bằng try/catch đồng bộ; một hàm async return về một Promise trước khi Promise đó settle, nên try/catch đồng bộ không bắt được rejection. Kết quả: lỗi rơi ra khỏi handler dưới dạng unhandledRejection , không tới error middleware, không được gửi thành 500 JSON , và từ Node 15 mặc định làm process crash. Fastify đi hướng khác — pipeline hook tự await handler, rejection được framework bắt và chuyển tới setErrorHandler . Hiểu điểm khác biệt này giải thích vì sao cùng một dòng code await db.query(...) lại có hai hệ quả production hoàn toàn khác nhau giữa hai framework. Cơ chế hoạt động Trong Express 4, Layer.handle_request gọi handler đồng bộ trong một khối try/catch . Nếu handler ném exception đồng bộ, catch được, forward qua next(err) . Nhưng handler async không ném — nó return về một Promise. Đến khi Promise reject, control đã ra khỏi khối try/catch từ lâu: // Đây là bản giản lược của cách Express 4 gọi handler: try { const ret = handler ( req , res , next ) // với async handler, ret là Promise (đã pending) // handler đã "return" — try/catch không còn hiệu lực với reject xảy ra sau } catch ( err ) { next ( err ) // chỉ chạy khi handler ném đồng bộ } Vì Express 4 không await ret và cũng không ret.catch(next) , một Promise reject không có bên nào bắt. Node emit unhandledRejection ở tầng process. Cách sửa chuẩn là wrapper: // asyncHandler: bọc handler async, forward reject vào next(err) export const asyncHandler = ( fn ) => ( req , res , next ) => Promise . resolve ( fn ( req , res , next )). catch ( next ) app . get ( ' /orders/:id ' , asyncHandler ( async ( req , res ) => { const order = await db . orders . findById ( req . params . id ) if ( ! order ) { res . status ( 404 ). json ({ error : ' not_found ' }); return } res . json ( order

2026-07-08 原文 →
AI 资讯

End-to-end Design Walkthrough — Full System Design

Full system design walkthrough: vì sao quy trình 5 bước quan trọng hơn thuật ngữ, và cái bẫy nhảy thẳng vào deep-dive Một buổi phỏng vấn system design 45–60 phút không đánh giá xem thí sinh biết bao nhiêu tên công nghệ, mà đánh giá xem thí sinh có xử lý được một bài toán mơ hồ theo một quy trình có kỷ luật hay không. Cùng đề "thiết kế URL shortener", người thất bại thường bắt đầu bằng "dùng Cassandra vì scale tốt" ngay ở phút thứ hai — chưa hỏi scale bao nhiêu, chưa biết read/write ratio, chưa đồng ý interface. Người pass đi theo một trình tự cứng: requirements → estimation → high-level → deep-dive → tradeoff . Cùng một đề, cùng thời lượng, nhưng người thứ hai dẫn dắt được interviewer thay vì bị dí. Bài này mô tả quy trình đó ở mức thực dụng, các thất bại thường gặp khi bỏ bước, và một hands-on end-to-end trên URL shortener để tự luyện. Cơ chế hoạt động Quy trình chuẩn được nhiều tài liệu tổng hợp (Alex Xu — System Design Interview vol.1; Donne Martin — system-design-primer ; Kleppmann — Designing Data-Intensive Applications ) đều có 4–5 bước gần như trùng nhau. Đây là khung 5 bước dùng thực tế trong phỏng vấn: Requirements clarification (~5 phút). Chốt functional requirement (hệ thống làm gì — API nào, use case nào) và non-functional requirement (availability target, latency target, consistency yêu cầu, security, cost). Không đoán — hỏi lại interviewer. Output: 3–5 gạch đầu dòng functional + 3–5 gạch NFR + danh sách "out of scope" (analytics, billing, ...). Back-of-the-envelope estimation (~5 phút). Tính DAU, QPS peak/avg, read:write ratio, storage growth theo năm, bandwidth. Không cần chính xác — cần đúng order of magnitude để quyết định "cần shard hay không", "cache có ý nghĩa không", "một node đủ hay phải scale ngang". High-level design (~10–15 phút). Vẽ box diagram: client → LB → app tier → cache → primary datastore → async worker → object storage/CDN. Định nghĩa API (endpoint, request/response, status code) và data model (schema chính, index chính). Ở bước này

2026-07-08 原文 →
AI 资讯

The ‘G-Wagen of golf carts’ could be the ideal second car

While the auto industry wrings its hands over the electric vehicle market, sweating details like aerodynamic efficiency and range anxiety, a new EV startup based in Lisbon, Portugal, is zagging in a different direction. Amble's new electric buggy won't impress anyone with its 0-60 time or its self-driving features (it has none). Instead, it takes […]

2026-07-08 原文 →
AI 资讯

Replication Monitoring — HA Dashboard

HA dashboard cho Postgres replication: vì sao "có replica" không đồng nghĩa "đang HA", và cách để replica chết không âm thầm Streaming replication trong Postgres là một tunnel WAL từ primary sang standby: primary chạy một walsender cho mỗi standby, standby chạy một walreceiver nhận WAL và một startup process replay. Đau nhất trong vận hành không phải setup — mà là replica đã ngắt nhiều giờ mà không ai biết, tới lúc primary chết mới phát hiện HA thực ra là single-node từ tuần trước. HA dashboard là tập metric + alert được rút ra từ pg_stat_replication , pg_stat_wal_receiver , và pg_replication_slots để ép mọi trạng thái xấu — replica disconnect, replay đứng, slot pin WAL, sync standby biến mất — thành tín hiệu nhìn thấy được trước khi biến thành sự cố. Cơ chế hoạt động Trên primary, mỗi standby đang kết nối tạo ra một backend loại walsender — Postgres đọc WAL từ pg_wal/ (hoặc từ WAL buffers khi còn nóng) và stream qua replication connection. Trên standby, walreceiver nhận từng WAL record, ghi vào pg_wal/ local, fsync (tùy synchronous_commit ), rồi startup process apply record lên shared buffers — đây chính là replay. Bốn LSN xuất hiện trong luồng này và tương ứng với bốn cột trong pg_stat_replication : sent_lsn — byte cuối cùng primary đã gửi qua socket. write_lsn — byte cuối cùng standby đã write() vào OS page cache. flush_lsn — byte cuối cùng standby đã fsync xuống đĩa. replay_lsn — byte cuối cùng standby đã replay vào shared buffers (dữ liệu đã "thấy được" trên standby). Postgres docs quy định replay_lsn <= flush_lsn <= write_lsn <= sent_lsn <= pg_current_wal_lsn() — bốn "vạch" này chính là bốn nhịp của lag. Ba cột write_lag , flush_lag , replay_lag (kiểu interval ) là thời gian mà standby chậm hơn primary tương ứng với ba mốc write/flush/replay — được đo qua feedback message định kỳ từ standby. -- Trên primary: bức tranh đầy đủ cho một HA dashboard SELECT application_name , client_addr , state , -- streaming | catchup | startup | backup | stopping sync_state , --

2026-07-07 原文 →
开发者

Get Ready For the Powerful CSS border-shape Property!

We recently got the shape() function and corner-shape property. What else could we possibly need as far as making shapes in CSS? Let me tell you: the border-shape property! Get Ready For the Powerful CSS border-shape Property! originally handwritten and published with love on CSS-Tricks . You should really get the newsletter as well.

2026-07-07 原文 →
AI 资讯

iRobot’s newest floor cleaner isn’t a robot

iRobot just announced its first-ever non-robotic floor cleaner. The $399 Roomba Electro Plus is a 5-in-1 hard-floor cleaner that combines vacuuming, mopping, and disinfecting, but you have to operate it yourself. The company also announced updates to its line of Roomba robot vacuums, launching five new models with higher suction power, smaller footprints, and lower […]

2026-07-07 原文 →
AI 资讯

How to Use Stream Analyzers for Digital TV Broadcasting: A Practical Guide

Part 1: Solving GOP Structure and Compatibility Issues Operating a digital television network isn't just about keeping channels on air—it's about maintaining quality that viewers expect and troubleshooting issues before they escalate. When something goes wrong in live broadcasting, every second counts. But how do you quickly pinpoint whether the problem lies in encoder settings, transport stream structure, or temporal metadata? This is where specialized stream analysis tools become essential. In this series of articles, we'll walk through real-world scenarios that broadcast engineers face daily and show practical approaches to diagnosing and resolving them. When File Analysis Becomes Critical While live monitoring catches issues as they happen, file-based analysis is your diagnostic microscope. Here's the typical workflow: something breaks in production, engineers capture a few minutes of the problematic stream, and now they need to understand exactly what went wrong. File analyzers serve three primary purposes: Troubleshooting: Identifying the root cause of broadcast issues Encoder optimization: Fine-tuning compression settings Quality control: Validating compliance with standards and specifications Let's explore how this works in practice with actual tools and techniques. The GOP Structure Problem Here's a scenario every broadcast engineer has encountered: legacy set-top boxes or older TV models suddenly can't play your stream. The audio works, video starts and stops, or you see freezing. The culprit? Often, it's the GOP (Group of Pictures) structure. H.264 has been around since 2003—over 20 years. Almost everything supports it, yet you'll still find legacy equipment that struggles with certain configurations. Specifically, the number of B-frames can make or break compatibility. Why B-frames matter: They enable lower bitrates while maintaining quality by increasing encoding complexity through bidirectional prediction. But this comes at a cost—a more complex refere

2026-07-07 原文 →