开发者
Building Dhrishti - Part 3: Testing on a Production Grade System
I was now done with the basic setup. However, during my time working at my startup, I have learnt to think about a project wearing multiple caps. One such aspect was - With Dhrishti running on a server that was already loaded, I did NOT want the tracking application itself to be heavy. I had to set some benchmarks to ensure that Dhrishti did not consume a tonne of space while tracking the metrics. I also had a problem with unresolved requests - in my mock_services, I had a client that was continuously hitting the API Gateway service. I had to fine-tune all the requests so that I could run tests under different loads, but the advantage was that my project was easily able to discern where the client request was coming from. However, in a production scenario, you can never know where a request is coming from - obviously, we cannot resolve different customer IPs to their respective customer names. This was the first problem. I had to specify what a customer was, and what an unknown request was. I came up with the following solution - Any unresolved IPs are going to be added to a table in the UI called unresolved IP table. This would help me with debugging later. Now, any unresolved IPs which also made requests to an ENTRY-POINT into my application could be added as the customers. For this, I very simply had to filter out the unknown IPs, and keep a configurable entry-point in dhrishti.json in which I would add a bunch of entry-points (in the case of my mock micro-service architecture, only 1) Now, I could differentiate between 2 types of unknown IPs - one which was potentially a customer, one which was a background network call, not important to the working system. The next problem was with the client service itself. It was difficult to simulate, say - a million users in my system. I had essentially built a service which was only being used by 1 customer, but how would Dhrishti behave if I added multiple client IPs? Using K6 k6 is a Grafana based application that helps
开发者
Andrew Yang thinks the next big startup opportunity is lowering the cost of living
Andrew Yang made a list of everything Americans overpay for — housing, food, wireless — and thinks the next startup gold rush is giving that money back.
AI 资讯
Switch an old script from Rhino to the V8 runtime
Originally written for bulldo.gs — republished here with the canonical link pointing home. I want to enable the V8 runtime on an existing Apps Script project so I can use modern JavaScript, but I am worried about breaking things that are already working. // appsscript.json — set runtimeVersion to enable V8 // Rollback: change V8 back to DEPRECATED_ES5 { " timeZone " : " America/New_York " , " dependencies " : {}, " exceptionLogging " : " STACKDRIVER " , " runtimeVersion " : " V8 " } // Code.gs — safe V8-compatible replacement for a common Rhino pattern // Rhino allowed: for each (var item in collection) {} // V8 requires standard for...of instead function listSheetNames () { var ss = SpreadsheetApp . getActiveSpreadsheet (); var names = []; var sheets = ss . getSheets (); for ( var i = 0 ; i < sheets . length ; i ++ ) { names . push ( sheets [ i ]. getName ()); } Logger . log ( names . join ( ' , ' )); } The one-line change and why it is a project-wide bomb Open the Apps Script editor, click Project Settings (the gear icon), and check "Show appsscript.json manifest file in editor." Then open that file and change "runtimeVersion": "DEPRECATED_ES5" to "runtimeVersion": "V8" . Save. That is the entire migration from a settings standpoint. What catches people off guard is the failure mode. V8 parses every .gs file in the project as a unit before running anything. One Rhino-only statement — a for each loop, a __iterator__ method, a Date.prototype.getYear call in an otherwise untouched utility file — causes a syntax or runtime error that prevents the whole script from initializing. Not just the file that contains the bad line. Every function, every trigger, the entire project goes dark. The first time I hit this it took me twenty minutes to figure out why a completely unrelated trigger had stopped firing. The error message pointed at the Rhino syntax in a helper file I had not touched in two years. V8 does not isolate the damage; it fails at parse time, before any executi
AI 资讯
Fix "Exceeded maximum execution time" in Apps Script
Originally written for bulldo.gs — republished here with the canonical link pointing home. I'm running a script that processes a large spreadsheet and it keeps dying with "Exceeded maximum execution time" before it finishes. // Checkpoint-resume pattern for long-running sheet jobs function processInBatches () { var props = PropertiesService . getScriptProperties (); var startRow = parseInt ( props . getProperty ( ' lastRow ' ) || ' 2 ' , 10 ); var sheet = SpreadsheetApp . getActiveSpreadsheet (). getActiveSheet (); var lastDataRow = sheet . getLastRow (); var BATCH = 200 ; var SAFE_MS = 5 * 60 * 1000 ; var started = Date . now (); var endRow = Math . min ( startRow + BATCH - 1 , lastDataRow ); var data = sheet . getRange ( startRow , 1 , endRow - startRow + 1 , 5 ). getValues (); for ( var i = 0 ; i < data . length ; i ++ ) { if ( Date . now () - started > SAFE_MS ) { props . setProperty ( ' lastRow ' , String ( startRow + i )); return ; } // process data[i] here } if ( endRow >= lastDataRow ) { props . deleteProperty ( ' lastRow ' ); deleteTrigger_ (); } else { props . setProperty ( ' lastRow ' , String ( endRow + 1 )); } } The 6-minute wall is per-execution, not per-task Apps Script enforces a hard 6-minute execution time limit per run, regardless of whether you're on a free account or a Workspace account (which bumps the limit to 30 minutes, but the same cliff exists). The error doesn't mean your logic is wrong; it means one continuous call to your function took too long. The fix is to stop thinking of your job as a single execution and start thinking of it as a pipeline of short runs. The first time I hit this, I wasted an afternoon trying to speed up the loop. Marginal gains didn't move the needle because the data volume was the real problem — 4,000 rows at one Sheets API call per row will always breach 6 minutes. The correct frame is: how do I save where I stopped and pick up there next run? Saving and restoring a cursor with PropertiesService PropertiesServic
AI 资讯
Coding-Agent Misalignment: Turn Failure Taxonomies into QA Checks
Coding agents are no longer just autocomplete with a longer prompt. GitHub describes Copilot cloud agent as software that can research a repository, create an implementation plan, make code changes on a branch, run in an ephemeral GitHub Actions-powered environment, and let a developer review or create a pull request afterward. OpenAI's Codex GitHub integration similarly positions code review as a repository-aware review pass that follows AGENTS.md guidance and focuses comments on serious issues. That shift changes the buyer question. The useful question is not "does the agent usually write code?" It is "can the team detect when the agent drifts away from the developer's intent before the change reaches production?" A May 2026 arXiv paper, "How Coding Agents Fail Their Users" , gives teams a better vocabulary for that review. The authors studied 20,574 real IDE and CLI coding-agent sessions across 1,639 repositories and define misalignment as a breakdown that becomes visible through developer correction or pushback. The paper reports seven recurring symptom categories: wrong project diagnosis, misread developer intent, developer constraint violation, self-initiated overreach, faulty implementation, operational execution error, and inaccurate self-reporting. Effloow Lab also ran a bounded OpenAI API check using three synthetic, non-confidential coding-agent transcript snippets. The run did not measure real-world incidence, compare vendors, or reproduce the paper. It produced a small rubric that maps visible symptoms to review gates such as diff-scope checks, evidence-before-edit checks, acceptance-criteria coverage, and verification-output requirements. The public lab note is available at /lab-runs/coding-agent-misalignment-failure-taxonomy-poc-2026 . This guide turns that research and lab output into a practical QA checklist for teams buying, piloting, or packaging coding-agent workflows. Why This Matters for Agent Buyers Coding-agent procurement often starts with p
开发者
Merge multiple docs into one in Google Docs
Originally written for bulldo.gs — republished here with the canonical link pointing home. I want to programmatically combine several Google Docs into one file without losing tables or list formatting. // Merges all source docs into destDocId, in order. // Run from the Apps Script editor; no triggers needed. function mergeDocs () { var sourceIds = [ ' DOC_ID_ONE ' , ' DOC_ID_TWO ' , ' DOC_ID_THREE ' ]; var dest = DocumentApp . openById ( ' DEST_DOC_ID ' ). getBody (); for ( var i = 0 ; i < sourceIds . length ; i ++ ) { var srcBody = DocumentApp . openById ( sourceIds [ i ]). getBody (); var total = srcBody . getNumChildren (); for ( var j = 0 ; j < total ; j ++ ) { var el = srcBody . getChild ( j ); var type = el . getType (); if ( type === DocumentApp . ElementType . PARAGRAPH ) { dest . appendParagraph ( el . asParagraph (). copy ()); } else if ( type === DocumentApp . ElementType . TABLE ) { dest . appendTable ( el . asTable (). copy ()); } else if ( type === DocumentApp . ElementType . LIST_ITEM ) { dest . appendListItem ( el . asListItem (). copy ()); } } } } Why there is no single appendElement call The Document service in Apps Script does not expose a generic appendElement method on Body . Every element type has its own typed append method: appendParagraph , appendTable , appendListItem , and so on. That means a merge loop that ignores element types will throw TypeError: el.copy is not a function the moment it hits a table, because you would be passing an Element where the API expects a Table . The fix is to call getType() on each child element and switch on DocumentApp.ElementType . The type enum values are strings like PARAGRAPH , TABLE , LIST_ITEM , INLINE_IMAGE , and HORIZONTAL_RULE . In practice the first three account for almost all real document content. The code above handles those three and silently skips anything else (images, rules) rather than crashing the entire merge. Getting the doc IDs and running the script The ID for any Google Doc is the lo
AI 资讯
Import JSON from an API in Google Sheets
Originally written for bulldo.gs — republished here with the canonical link pointing home. I want to pull live JSON data from an API endpoint directly into a Google Sheet without installing an add-on. // Fetch JSON from an API and write it to the active sheet // Adjust API_URL and the field list to match your endpoint function importJsonFromApi () { var API_URL = ' https://jsonplaceholder.typicode.com/users ' ; var sheet = SpreadsheetApp . getActiveSpreadsheet (). getActiveSheet (); var response = UrlFetchApp . fetch ( API_URL ); var raw = response . getContentText (); var data = JSON . parse ( raw ); var headers = [ ' id ' , ' name ' , ' username ' , ' email ' , ' phone ' ]; var rows = data . map ( function ( obj ) { return headers . map ( function ( key ) { return obj [ key ] || '' ; }); }); sheet . clearContents (); sheet . getRange ( 1 , 1 , 1 , headers . length ). setValues ([ headers ]); sheet . getRange ( 2 , 1 , rows . length , headers . length ). setValues ( rows ); } Why getContentText() comes before JSON.parse UrlFetchApp.fetch() returns an HTTPResponse object, not a string. The first time I skipped getContentText() and passed the response object directly to JSON.parse(), it silently parsed to null and the sheet wrote nothing. You need raw = response.getContentText() to get the actual body as a string, then JSON.parse(raw) turns it into a JavaScript object or array. The URL must be publicly accessible or accept an API key via a query parameter or Authorization header. Add headers like this: UrlFetchApp.fetch(url, { headers: { Authorization: 'Bearer ' + token } }). Apps Script's UrlFetchApp quota is 20,000 calls per day on a free Google account, 100,000 on Workspace. The rectangular array constraint — why setValues fails without mapping setValues() is strict: it requires a 2D array where every row has the same number of columns. If you hand it an array of plain JSON objects, it throws 'The number of rows or columns in the range does not match the number of
AI 资讯
Send personalized emails from a sheet in Gmail
Originally written for bulldo.gs — republished here with the canonical link pointing home. I have a spreadsheet of names and email addresses and I want to send each person a personalized message from my Gmail account without copy-pasting or using a paid tool. // Mail merge: Sheet cols A=Name, B=Email, C=Sent // Run from Apps Script; authorize Gmail + Sheets scopes function sendMerge () { var sheet = SpreadsheetApp . getActiveSheet (); var rows = sheet . getDataRange (). getValues (); var quota = MailApp . getRemainingDailyQuota (); var sent = 0 ; for ( var i = 1 ; i < rows . length ; i ++ ) { if ( rows [ i ][ 2 ] === ' Sent ' ) continue ; if ( sent >= quota ) { Logger . log ( ' Quota reached at row ' + ( i + 1 )); break ; } var name = rows [ i ][ 0 ]; var email = rows [ i ][ 1 ]; var subject = ' Hey ' + name + ' , here is your update ' ; var body = ' Hi ' + name + ' , \n\n Your personalized content goes here. \n\n Thanks ' ; MailApp . sendEmail ( email , subject , body ); sheet . getRange ( i + 1 , 3 ). setValue ( ' Sent ' ); sent ++ ; } } Set up your sheet and open the script editor Put names in column A, email addresses in column B, and leave column C blank — the script writes 'Sent' there as it goes. Header row in row 1 is assumed; the loop starts at index 1 (row 2) to skip it. Open the script editor from Extensions > Apps Script, paste the function, and save. The first time you run sendMerge() Google will ask you to authorize two scopes: Sheets (read/write the active spreadsheet) and Gmail (send mail on your behalf). Both are required. If you only see a Sheets prompt, delete the file and re-paste — a cached partial authorization sometimes skips the Gmail scope on older script files. Why the Sent column is the whole point Consumer Google accounts cap at roughly 100 outgoing recipients per 24-hour rolling window via MailApp. If your list has 200 rows and you run the script at 11 pm, it will send 100 and log 'Quota reached at row 101'. Without the Sent check, a sec
开发者
Remove duplicate rows in Google Sheets
Originally written for bulldo.gs — republished here with the canonical link pointing home. I have a Google Sheet with duplicate rows and I want to remove them programmatically, either on demand or on a schedule, without destroying the rest of my data. // removeDuplicates.gs — dedup active sheet, keep first occurrence // Run from Extensions > Apps Script, or bind to a trigger. function removeDuplicateRows () { var sheet = SpreadsheetApp . getActiveSheet (); var data = sheet . getDataRange (). getValues (); var seen = new Set (); var unique = []; for ( var i = 0 ; i < data . length ; i ++ ) { var key = data [ i ]. join ( ' | ' ); if ( ! seen . has ( key )) { seen . add ( key ); unique . push ( data [ i ]); } } sheet . clearContents (); sheet . getRange ( 1 , 1 , unique . length , unique [ 0 ]. length ). setValues ( unique ); } Why rewrite instead of delete The instinct when deduplicating is to loop through the sheet and call deleteRow on each duplicate. That works, but it has a sharp edge: every call to deleteRow shifts all rows below it up by one. If you delete row 3, what was row 4 is now row 3, and your loop index is already pointing at the new row 4. The safe workaround people reach for is iterating bottom-to-top, which works but means holding the full duplicate set in memory anyway, making one API call per deleted row. The approach here sidesteps the problem entirely. Read everything once with getDataRange().getValues() — a single API call that returns a 2D array. Build the deduplicated array in JavaScript using a Set to track which row fingerprints you have already seen. Then clear the sheet and write the result back with one setValues call. Two API calls total, regardless of how many duplicates you had. For a 10,000-row sheet, this is the difference between a script that finishes in two seconds and one that times out at the six-minute Apps Script execution limit. The row key is built with data[i].join('|'). The pipe character works as a separator in practice; i
产品设计
Friday Squid Blogging: Squid-Inspired Fluid Pump
This fluid pump was inspired by the way squids propel themselves through the water. As usual, you can also use this squid post to talk about the security stories in the news that I haven’t covered. Blog moderation policy.
AI 资讯
China Didn't Make People Hate Data Centers
GOP lawmakers, tech investors, and even OpenAI have tied the anti-data center movement in the US to Chinese interference. Experts say it’s much more complicated than that.
AI 资讯
Google Launches Colab CLI for Developers, Automation, and AI Agents
Google has announced the Google Colab CLI, a command-line tool that allows developers and AI agents to interact with remote Colab runtimes directly from a local terminal. By Daniel Dominguez
AI 资讯
When it comes to total water use, AI data centers are a drop in the bucket
Even moderately sized data centers can have an outsized local impact.
AI 资讯
Google sues Chinese cybercrime network that used Gemini to automate scams
The fraudsters allegedly targeted hundreds of thousands of people with Gemini-coded scams sites.
AI 资讯
US surveillance law to expire for first time after lawmakers reject Trump’s controversial pick to lead spy agencies
The spy law known as Section 702, which authorizes the NSA and FBI's warrantless surveillance, will all but certainly expire on Friday for the first time.
AI 资讯
Bernie Sanders’ AI Sovereign Wealth Fund Plan
Let no one accuse Bernie Sanders of ducking the big questions. Writing in the New York Times last week, the senator asked : “Will the future of humanity be determined by a handful of billionaires who have promoted and developed AI, with virtually no democratic input, who stand to become even richer and more powerful than they are today?” We agree entirely that this is one of the most potent questions facing global democracy today. Our book, Rewiring Democracy , surveys the emerging uses for and impacts of AI in democracy around the world and reaches the same conclusion: that the most urgent risk posed by AI is the ...
AI 资讯
I Built a Stable Sorting Algorithm That Beats Java's Dual-Pivot Quicksort
A few days ago I finished benchmarking something I've been building - a cache-aware, stable, histogram-based sorting algorithm I'm calling BusSort . The results surprised even me. At 100 million elements, it runs ~2x faster than Java's Dual-Pivot Quicksort on random data - while being stable . Dual-Pivot QS is not. The Problem With Quicksort at Scale Quicksort-based algorithms partition elements with random writes across the entire array. At large scales this causes cache thrashing - elements are being written to memory locations all over the place, constantly missing L1 and L2 cache. The larger the array, the worse it gets. The Core Idea Instead of scattering elements globally, BusSort processes data in L1 cache-sized chunks - 4096 integers (~16KB). For each chunk, it does 4 passes: PASS 1 - Scan left-to-right, compute bucket for each element, build a local histogram PASS 2 - Compute local prefix sums (bucket positions within the chunk) PASS 3 - Scatter into a local grouped buffer - because this buffer is L1-sized, all random writes stay in cache ✅ PASS 4 - Copy each bucket's portion to its correct global position With 128-way splitting , recursion depth stays at just ~4 levels even for 100M elements. Base case: Insertion Sort for ≤ 1024 elements. On the benchmark machine (i5-1135G7, 48KB L1 data cache): 4096 × 3 × 4 bytes = 49,152 bytes ≈ 48KB The three working arrays fit exactly in L1. Not a coincidence. Benchmark Results Tested against Arrays.sort(int[]) - Java's Dual-Pivot Quicksort . n = 100,000,000 | Java 17 | i5-1135G7 @ 2.40GHz Input Type BusSort Dual-Pivot QS Ratio Random 3991ms 8604ms ~2x Sorted 57ms 104ms ~2x Reverse 280ms 166ms 0.6x Nearly Sorted 2452ms 2789ms ~1.1x Duplicates 712ms 2242ms ~2.4x Few Duplicates 1295ms 3185ms ~2.3x All Same 51ms 32ms 0.6x Clustered 1419ms 2242ms ~1.6x Consistently faster on most input types. Stable. Zero comparison overhead. The two losses (Reverse, All Same) are where Dual-Pivot QS has structural advantages - run detecti
AI 资讯
These are the countries moving to ban social media for children
Australia was the first country to issue a ban in late 2025, aiming to reduce the pressures and risks that young users may face on social media, including cyberbullying, social media addiction, and exposure to predators.
AI 资讯
The Person, Not the Cards
In December 2025, Anthropic acquired Bun , the JavaScript runtime written in Zig. In April 2026, the Bun team announced a 4× compile-time improvement on their fork of the Zig compiler — "parallel semantic analysis and multiple codegen units to the llvm backend" , in their phrasing. They also announced they would not be upstreaming the work, "as Zig has a strict ban on LLM-authored contributions." The framing landed badly with Zig observers, for two reasons. The first was that the framing made Zig's contribution policy the obstacle. The second, pointed out shortly afterwards by a Zig core contributor in the Ziggit thread, was that the patch had separate engineering reasons it would not have been merged regardless: "Parallel semantic analysis has been an explicitly planned feature of the Zig compiler for a long time" , with "implications not only for the compiler implementation, but for the Zig language itself" . The AI-ban explanation was, on a closer read, a tidy way of declining to litigate the engineering disagreement in public. Both readings are useful. They are also both downstream of the actual rationale, which is one of the most carefully argued OSS-governance documents to appear in 2026. What the policy actually says The relevant clauses, in the Zig code of conduct under the section heading Strict No LLM / No AI Policy , are three: No LLMs for issues. No LLMs for pull requests. No LLMs for comments on the bug tracker, including translation. English is encouraged, but not required. You are welcome to post in your native language and rely on others to have their own translation tools of choice to interpret your words. The translation clause is the surprising one. It is also the one that disambiguates the policy from a code-quality rule. A blanket ban on LLM-mediated communication, including translation, is not a heuristic about whether agentic tools produce good code. It is a stance about what the project's communication channels are for . Contributor poker Lor
AI 资讯
Congrats to the Google I/O 2026 Writing Challenge Winners!
We are so excited to announce the winners of the Google I/O 2026 Writing Challenge ! We asked you to explore the announcements from Google I/O 2026 and share your thoughts and firsthand takes. Wow, you delivered. The quality and depth of submissions genuinely impressed our team. From hands-on walkthroughs to bold opinions on what the announcements really mean for developers, the entries were thoughtful, original, and packed with insight. Thank you to everyone who participated. Your writing helps make this community one of the best places on the internet to learn what's actually happening in tech. Now, let's celebrate our five winners! 🎉 🏆 Congratulations To… The Sleeper Announcement from Google I/O 2026 That Will Change How We Think About Apps Google I/O Writing Challenge Submission Vrushali Vrushali Vrushali Follow May 24 The Sleeper Announcement from Google I/O 2026 That Will Change How We Think About Apps # devchallenge # googleiochallenge # android # kotlin 7 reactions 2 comments 7 min read @vrushali_dev_15 wrote a standout deep-dive into AppFunctions — Android's new API for exposing app capabilities directly to AI agents. With 10 years of Android experience behind the lens, this post goes far beyond the surface announcement to map out the full architectural shift this signals and what developers should be thinking about right now, even before shipping a single AppFunction. I gave Gemini 3.5 Flash a CVE-fix PR to review. It found another bug in the same file. Google I/O Writing Challenge Submission Vicente Junior Vicente Junior Vicente Junior Follow May 22 I gave Gemini 3.5 Flash a CVE-fix PR to review. It found another bug in the same file. # googleiochallenge # devchallenge # ai # gemini 9 reactions 1 comment 7 min read @vicente_junior_dev did something rare: actually tested the thing. Running Gemini 3.5 Flash across 3 real production PRs, including a CVE fix, the post documents what the model caught. Grounded, honest, and exactly the kind of first-person expe