AI 资讯
I built an MCP memory server for one user (me, for six weeks)
Building in public You explain your deploy setup to your assistant. It helps. Tomorrow you explain the same setup again. And the day after. You are not training it. You are re-typing. The tool nobody asked for I did not set out to build a product. I set out to stop repeating myself. My setup is four servers with names that mean nothing to anyone else, a tunnel with a numbering scheme I keep getting wrong, and a dozen small traps that only exist because of decisions I made two years ago. Every new session started from zero. So I gave the assistant a place to write things down, and a way to read them back before it started working. Two calls: one to save what was learned, one to recall it. That was the whole idea. For six weeks it had exactly one user. Nobody else could have used it, because I had not written a single line of documentation. Six weeks of being my own only customer That stretch turned out to be the most valuable part, and not because of what got built. Because of what got measured. When you are the only user, every rough edge lands on you within a day. A recall that returns the wrong thing costs you the next hour. A save that silently drops a field costs you the next week, when you go looking for it. I kept a count of the times the memory actually prevented a mistake. Not a feeling, a count. After six weeks it was high enough that I stopped arguing with myself about whether the thing was worth the effort. The uncomfortable part: several of those saved lessons were about mistakes I had already made twice. The tool did not make me smarter. It made me stop paying for the same lesson. The moment it stopped being a personal tool The thought that changed it was not a market analysis. It was smaller and more honest: if I find this useful, and my setup is not special, then somebody else is retyping their own servers right now. That is a weak argument on its own. Plenty of internal tools are useful precisely because they fit one person. So I looked for the part
AI 资讯
Flux Mirror Uses Gitless GitOps to Keep Software Supply Chain Under Control
Flux has introduced Flux Mirror, a CLI plugin that mirrors container images, Helm charts and OCI artifacts between registries from a declarative configuration. The plugin is part of the Flux v2.9 CLI plugin system and is presented as a way to keep Kubernetes clusters reconciling only from registries that teams operate themselves. By Matt Saunders
AI 资讯
Physical Server vs Cloud Server: Which Infrastructure Makes More Sense?
When building an application, we usually focus on the frontend, backend, APIs, and database. But there is another important question: Where should the application actually run? Two common approaches are physical servers and cloud/virtual servers. Understanding the difference is important because infrastructure decisions affect scalability, availability, security, maintenance, and cost. What Is a Server? A server is a computer system that runs applications, processes requests, communicates with databases, and provides information to users. A typical request might look like: User → Internet → Application Server → Backend → Database → Response Depending on the application, the server may handle authentication, APIs, user data, file processing, notifications, and other backend operations. In simple terms, the server provides the execution environment behind the application. Physical Server: More Control, Less Flexibility A physical server is a dedicated machine used to run applications. For example: 16 CPU cores + 64 GB RAM + 2 TB SSD Advantages: • Dedicated hardware • Predictable performance • Greater hardware-level control • Suitable for stable workloads Limitations: • Higher initial investment • Hardware maintenance • Hardware failures can cause downtime • Scaling requires additional or upgraded hardware If an application suddenly grows beyond the capacity of the machine, increasing capacity may require purchasing and configuring new hardware. Cloud / Virtual Server: Infrastructure That Can Adapt A cloud server is a virtual server running on physical infrastructure inside a cloud data center. For example: 4 vCPU + 16 GB RAM + SSD Instead of purchasing the entire physical machine, resources can be provisioned according to the application's requirements. Cloud environments also provide different scaling approaches. Scale Up: Increase the resources of an existing server. 4 vCPU → 8 vCPU → 16 vCPU Scale Out: Add additional application instances. Application Server 1 + Ap
AI 资讯
Self-Hosted Chatwoot: 5 Failures the Docs Don't Warn You About
I run self-hosted Chatwoot as the WhatsApp inbox for a dozen or so small Israeli businesses. Two servers, a few thousand conversations a week, a drip-sequence engine bolted on the side. Chatwoot is good software. The self-hosting docs will get you to a running container. What they will not tell you is which failures actually happen at month six, when you have real customers and real volume. These five all bit me in production, and none of them looked like what they were. 1. Your disk fills from somewhere Postgres never sees I got a disk alert at 86 percent and immediately went looking at the database. That was the wrong place. DB (postgres): 680 MB chatwoot_storage_data: 17 GB Attachments live in ActiveStorage, on a Docker volume, not in Postgres. Every image, voice note, and PDF a customer sends is a file on disk, and none of it shows up when you check database size. If your monitoring watches the DB, it will report everything is fine right up until the container cannot write. The growth curve is a function of how many accounts you host, not how busy any one of them is. Mine sat at roughly 0.05 GB a month until I onboarded seven new businesses over two months, and then it hit 16 GB a month. Check the right volume: docker system df -v | grep chatwoot_storage_data 2. Forty-four percent of my outbound storage was duplicate files This is the part that surprised me. When I actually measured what was on that volume, almost half the outbound media was byte-identical copies of the same file. One 14.5 MB video was stored 48 separate times. One image was stored 325 times. Chatwoot creates a new blob and a new file on disk on every send, even when the bytes are identical. That is correct behavior for a chat app where every message owns its attachment. It becomes expensive the moment you have anything that fans one file out to many conversations. In my case it was not campaigns at all, it was the drip engine sending the same media to 48 separate conversations as ordinary outbo
AI 资讯
Deploying Multiple Python Bots to a Single Railway Container
A tutorial for running two or more python bots on Railway inside one container and one service, with independent crash recovery for each. Deploying Multiple Python Bots to a Single Railway Container If you're running more than one Python bot — say, a Telegram ingestion bot and a Discord notification bot that share a database — deploying each as its own Railway service means double the hosting cost and double the configuration for something that's logically one unit. This tutorial covers deploying both bots inside a single Railway container, with each one still getting fully independent crash recovery. Table of Contents Why Two Services Is Usually Overkill The Naive Fix and Why It Falls Short Step 1: Install StayPresent Step 2: Structure Your Project Step 3: Configure Multiple Bots in One Entry Point Step 4: Read Railway's Assigned Port Step 5: Deploy as a Single Railway Service Verifying Both Bots Are Running FAQs Conclusion Why Two Services Is Usually Overkill Railway (like most PaaS platforms) charges per service, and each service needs its own configuration, environment variables, and deployment pipeline. If two bots are closely related — sharing a database, a queue, or just conceptually belonging to the same project — running them as two separate Railway services duplicates all of that for no real benefit. The Naive Fix and Why It Falls Short A common first instinct is a shell script: python telegram_bot.py & python discord_bot.py & wait This runs both, but there's no real process supervision here — if telegram_bot.py crashes, nothing restarts it, and you still haven't solved Railway's HTTP port requirement, since neither script opens one. Step 1: Install StayPresent pip install staypresent[prod] # requirements.txt staypresent[prod] Step 2: Structure Your Project project/ ├── main.py ├── telegram_bot.py ├── discord_bot.py ├── requirements.txt Both bot scripts stay exactly as they are — nothing about their internal logic needs to change. Step 3: Configure Multipl
AI 资讯
How to Track AI Code Assistant Spend Across Every Vendor (2026 Guide)
Most engineering organizations now pay several vendors for AI coding assistants, each one bills differently, and no single person in the company can answer the simplest question: what did our AI coding tools actually cost this month, and what did we get for it? This guide is the practical answer — the metrics that matter, the ways teams track spend, a step-by-step setup, and an honest maturity model for governing it. The short answer To track AI code assistant spend across every vendor, pull cost and usage from each tool's admin or billing API, normalize it into one model — because every vendor bills on a different unit and a different clock — and map it to your teams and cost centers. The four approaches teams use are manual spreadsheets, each vendor's native dashboard, an open-source usage CLI, and a dedicated AI spend management platform. Only the last gives finance, engineering, and IT one live number plus forecasting, anomaly detection, and per-developer and per-pull-request cost. If you only do three things: inventory every assistant in use, including shadow tools bought on personal cards; connect each vendor read-only and normalize to a common cost model; and instrument the leading indicators — premium-model mix, token or credit runway, and idle seats — because they move before the invoice does. What "AI code assistant spend" means AI code assistant spend is the total cost an organization pays across all of its AI coding tools — commonly GitHub Copilot, Cursor, Anthropic Claude, OpenAI, and others teams connect — including per-seat license fees, metered token or credit consumption, premium-model surcharges, and the hidden cost of idle or duplicate licenses. It sits at the application layer, which distinguishes it from general cloud cost (compute, storage, networking), and it concerns money and utilization, which distinguishes it from AI model governance and its focus on model risk and compliance. Why it's genuinely hard to track (and got harder in 2026) There
AI 资讯
Docker Launches Fully Rebuilt Virtualization Layer to Boost Performance and Improve Dev Experience
Docker VMM (virtual machine monitor) is Docker's new, first-party virtualization layer for Docker Desktop, replacing third-party virtualization components with an engine that Docker can directly control and optimize specifically for container workloads. The public beta launched with Docker Desktop 4.86 for Mac and Windows. By Sergio De Simone
AI 资讯
Idle load balancers: the ~$16/month each you forgot to delete"
Short version: An Application or Network Load Balancer costs ~$0.0225/hour, about $16/month, just to exist , plus capacity units. Classic Load Balancers run ~$18/month. Load balancers outlive the services behind them: the app gets torn down, the ALB keeps billing. Here's how to find load balancers with no real traffic or no healthy targets, and remove them safely. Why idle load balancers linger The hourly base charge is fixed - an ALB with zero requests bills the same ~$16/month as a busy one. Load balancers are usually created early (with an app or an IaC module) and deleted last, if ever. A handful of abandoned ALBs from old environments is real, recurring money. Step 1 - List load balancers and their traffic aws elbv2 describe-load-balancers \ --query 'LoadBalancers[].{Name:LoadBalancerName,Type:Type,ARN:LoadBalancerArn}' \ --output table For an ALB, check request volume over the last 7 days (the metric dimension is the tail of the ARN, e.g. app/my-alb/50dc6c495c0c9188 ): aws cloudwatch get-metric-statistics \ --namespace AWS/ApplicationELB \ --metric-name RequestCount \ --dimensions Name = LoadBalancer,Value = app/my-alb/50dc6c495c0c9188 \ --start-time " $( date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ ) " \ --end-time " $( date -u +%Y-%m-%dT%H:%M:%SZ ) " \ --period 86400 --statistics Sum \ --query 'Datapoints[].Sum' Near-zero request counts over a week is a strong idle signal. (For NLBs, use the AWS/NetworkELB namespace and ActiveFlowCount .) Step 2 - Check for empty or unhealthy target groups A load balancer with no healthy targets is doing nothing useful: for tg in $( aws elbv2 describe-target-groups \ --load-balancer-arn <lb-arn> \ --query 'TargetGroups[].TargetGroupArn' --output text ) ; do echo "== $tg ==" aws elbv2 describe-target-health --target-group-arn " $tg " \ --query 'TargetHealthDescriptions[].TargetHealth.State' --output text done Empty output (no targets) or all unhealthy alongside near-zero requests is a confident "delete me." Step 3 - Delete saf
AI 资讯
Opinion: AI Server Changes Need a Fault Drill, Not Just a Rollback Plan
A rollback plan tells you how to undo an AI change, but not what breaks first when the change stays in place. Most production incidents do not begin with a deliberate rollback; they begin with an unexpected failure mode that the author never tested. I now treat a passing fault drill as a precondition for reviewing any AI-generated server patch. The drill runs on a disposable server before a human reads a single line of the diff. Why a rollback plan is not enough A rollback plan answers a question about the past: how do we return the system to a known state? A fault drill answers a question about the future: what happens when this change meets a condition the author did not imagine? The second question decides whether you get paged at 3 a.m. A change with a perfect rollback can still fail in a way that nobody notices until the data is gone. Free model access changes the economics of this argument, because generation stops being the bottleneck and verification starts. When a draft is nearly free, the cheapest verification is the one that breaks the change on purpose. A rollback plan is documentation; a fault drill is evidence. Documentation tells you what should happen, while evidence tells you what actually happens on a real service manager. The fault drill in five steps The workflow assumes two cheap resources: a model that generates failure hypotheses from a diff, and a server that can be destroyed after the drill. MonkeyCode's free model access covers the first, and its free server option covers the second, so a drill costs almost nothing. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Any ephemeral VM or container host works if you prefer a different provider. 1. Generate failure modes before you apply anything Ask the model to enumerate failure modes for the diff, and forbid it from proposing fixes, because fixes are a distraction at this stage. The prompt below is the one I use, and it produces a catalog that the drill can test.
产品设计
S3 Egress Fees: Why Downloading Your Own Data Costs So Much
Cross-posted from the Runsite blog . You put a few hundred gigabytes of images on object storage, glance at the pricing page, and the numbers look friendly: storage is a couple of dollars a month, basically a rounding error. Then the first real invoice arrives and it's a hundred and something. Nothing about how much you're storing changed. The line that blew up isn't storage at all. It's egress — the charge for data leaving the bucket — and it's the part of the bill nobody shops on. Why the storage bill blows up after the first invoice The pricing page wasn't lying to you. Object storage genuinely is cheap to sit on. On AWS S3 , standard storage runs about $0.023 per GB per month at the time of writing, so a hundred gigabytes of assets costs you around two dollars and change to keep. That's the number you compare when you're choosing where to put your files. The number you don't compare is egress: the fee for moving data out of the provider's network. It doesn't show up when you upload, and it doesn't show up while the files just sit there. It shows up every time someone downloads something — roughly $0.09 per GB to the internet once you're past a small free allowance (about the first 100 GB a month on AWS). Individually those are tiny fractions of a cent. The trouble is you're not billed once. You're billed per download, and a popular file gets downloaded a lot. Where egress hides Egress is data transfer out: every byte that leaves the provider's network. The reason it surprises people is that it isn't a single line you can point at. It's a multiplier that quietly attaches itself to things you'd never think of as "downloading": Serving assets to users. Every image, video, PDF, or download your app hands to a visitor is egress. One 4 MB hero image on a page that gets a million views a month is four terabytes of transfer out, from a single file. CDN origin pulls. Putting a CDN in front of your bucket helps, but it isn't free. Every cache miss means the CDN fetches th
AI 资讯
I Deliberately Destroyed My Kubernetes Cluster at 2 AM. Here's What Died First.
I Deliberately Destroyed My Kubernetes Cluster at 2 AM. Here's What Died First. Chaos engineering is not about breaking things. It's about discovering that your "production-grade" homelab is held together by hope and a single etcd snapshot before someone else finds out for you. The Setup I was lying in bed at 1:47 AM, staring at the ceiling, unable to sleep. Not because of caffeine. Because of a thought that had been gnawing at me for weeks: If one of my nodes died right now, would my cluster actually survive? I run a 4-node bare-metal Kubernetes cluster on Talos Linux. Dell OptiPlex control plane. Three Raspberry Pi workers. Cilium eBPF. ArgoCD. Longhorn distributed storage. Prometheus. Grafana. The whole cloud-native stack, shoehorned into $220 of scrap hardware and stubbornness. From the outside, it looks solid. ArgoCD syncs green. Cilium status shows healthy. Longhorn volumes are replicated across three nodes. I have etcd snapshots every 6 hours to S3. On paper, I'm resilient. But I had never actually tested it. Not a controlled test. Not a graceful node drain. I mean chaos . Sudden death. The kind of failure that happens at 3 AM when a power supply dies, or a kernel panics, or a neighbor's construction crew hits the wrong breaker. So I got out of bed, walked to my desk, and installed Chaos Mesh. Why Chaos Engineering on a Homelab? Professionally, I design AWS infrastructure with multi-AZ failover, auto-scaling groups, and managed services that abstract failure away. At Siemens, if an EKS node dies, the managed node group replaces it before I finish reading the alert. But my homelab has no managed control plane. No AWS SLA. No auto-repair. If a Pi's USB boot drive corrupts, that node is gone until I physically fix it. I needed to know: What dies first when a worker vanishes? Not "what should die" — what actually dies. Does Longhorn really failover? Three replicas sound great until you realize two of them were on the same node. Does Cilium handle network partitio
AI 资讯
DNS Troubleshooting with dig: The Commands DevOps Engineers Actually Need
A surprising share of "the app is down" pages resolve to a name-resolution problem, not a broken service. The service is fine; the client can't turn a name into an address. dig is the precision tool for proving that in seconds instead of guessing. Think about it as a resolution chain, not "is DNS broken" When a name fails, work the chain: which resolver did the client ask, what did that resolver return, and does it match what authoritative DNS actually says? Most incidents live in the gap between those three. The method is boring and reliable: observe the symptom, form a hypothesis about where in the chain it breaks, test with one query, read the evidence, fix, then validate. The single most important habit: query the name from the same host and the same resolver the app uses. Running dig from your laptop proves nothing about what the pod or VM sees. The record types worth knowing You don't need all of them, but you need to recognize them: A / AAAA — name to IPv4 / IPv6 address. The usual suspect. CNAME — an alias pointing at another name. A stale or wrong CNAME sends traffic somewhere unexpected. MX — mail routing. TXT — SPF, DKIM, domain verification, and other metadata. NS — which servers are authoritative for a zone. SOA — the zone's serial and TTL defaults; the serial tells you whether a change has propagated. PTR — reverse lookup, IP back to name. The commands that actually earn their place Start with the quick answer, then get precise. dig +short api.internal.example.com +short strips everything except the answer. If it prints an IP, resolution works from this host. If it prints nothing, you have a real failure to chase. Empty output is a signal, not an error. dig api.internal.example.com A The full form. Read the status in the header: NOERROR with an ANSWER section is good; NXDOMAIN means the name genuinely doesn't exist; SERVFAIL points at a broken upstream or DNSSEC issue. Also note which SERVER answered at the bottom — that's the resolver you're actually
AI 资讯
I Built a 40-Minute Evaluation for Free Model Endpoints. Here's the Scorecard.
Free model endpoints are seductive. Zero cost. Zero setup. Zero reason to trust them. I don't trust demos. I trust failure modes. So I built a small evaluation harness. It tests one thing: can a free model endpoint gate a pull request for secrets? This is not a benchmark. It's a repeatable experiment. You can run it in an afternoon. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I used MonkeyCode's free model endpoint and the free server option for the test. No quotas. No hardware claims. Just a harness and a rubric. Why I stopped trusting free endpoints Free endpoints look great in a demo. You paste a diff. The model finds the secret. Everyone claps. Then you wire it into CI. The JSON breaks. The latency spikes. The model misses a private key. The demo didn't show that. An evaluation will. The experiment I designed a 40-minute test. It answers one question: where does the free endpoint perform well, and where does it break? The dataset is 30 synthetic diffs. Fifteen contain real-looking secrets. Fifteen are clean. Each diff is small. Each diff has one clear change. The prompt is strict. The model must return JSON. No prose. No apologies. Just a verdict. # eval_secret_gate.py # Simplified harness. Adapt to your client SDK. import json , time def classify ( client , diff : str ) -> dict : prompt = f """ You are a secret scanner for code review. Return ONLY JSON with this shape: {{ " contains_secret " : true, " line " : 12, " type " : " aws_access_key " }} Diff: { diff } """ start = time . time () response = client . complete ( prompt , model = " free " , server = " free " , # free server option ) latency = time . time () - start return { " latency " : latency , " raw " : response } def evaluate ( client , diffs , runs = 3 ): for i , diff in enumerate ( diffs ): for run in range ( runs ): yield i , run , classify ( client , diff ) The harness is deliberately small. It measures five things. Accuracy. JSON validity. Latency. Variance. Fa
AI 资讯
Opinion: The Diff Is a Claim, the Probe Is the Proof
Opinion: The Diff Is a Claim, the Probe Is the Proof A generated patch is a claim about how a system should behave, and a diff cannot verify that claim on its own. The only honest reviewer is the runtime itself, which means every AI-proposed change deserves a behavioral probe before a human spends attention on it. Free model access changes the economics of that review, because the verification loop no longer costs a developer's full attention or a paid compute budget. The practical implication is that a disposable server, such as the free server option in MonkeyCode, becomes the arbiter of whether a patch is even worth reading. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Review sessions routinely burn forty minutes on a diff that a five-second HTTP probe would have rejected instantly, and that waste is now entirely avoidable. Why Line-by-Line Review Fails on AI Patches A human reviewer reads a diff as prose, searching for the author's intent, but an AI-generated patch has no reliable intent to recover. The model that wrote the change cannot explain why a specific flag was flipped, and the diff itself only records the surface edit. This is a fundamental mismatch between the review tool and the review question. The review question is not "what changed" but "does the system still behave correctly after this change." Runtime shape diffing answers the first question well, and I have argued before that shape is a useful gate, but shape alone misses semantic regressions. A service can keep the same endpoints, the same config keys, and the same file layout while silently returning wrong data. Behavioral probes close that gap because they test the contract between the service and its callers. A probe sends real requests, checks real responses, and records real state transitions, which is exactly the evidence a reviewer needs. This is why I take the position that the probe, not the diff, should be the primary review artifact. Treat Every Pa
AI 资讯
Multi Agent Collaboration Gets Persistent Compute in Bedrock AgentCore
Amazon Web Services has extended Amazon Bedrock AgentCore with runtime instances, a new compute option that gives AI agents persistent infrastructure purpose-built for complex long-running workflows and multi-agent coordination. By Matt Saunders
AI 资讯
UFW and WireGuard: the tunnel is up and nothing goes through
The tunnel comes up. wg show prints a recent handshake. The client has its address inside the tunnel. And not a single byte reaches the internet. Almost every guide answers this with "open UDP 51820 in the firewall". You already did that — it is why the handshake works at all. The problem is somewhere else, and UFW makes the distinction easy to miss: Entering a machine and traversing it are two different permissions. ufw allow 51820/udp lets packets arrive at the server. Your clients' traffic does not stop there — it goes through the box and out the public interface. That path lives in the FORWARD chain, which UFW denies by default and which no allow rule touches. The four things to check, in order 1. IP forwarding — and the file that overwrites the other file This is the one that costs hours, because the setting looks done. UFW loads its own sysctl file at startup, and it takes precedence over the system one. A value you carefully set in /etc/sysctl.conf can be silently overwritten on the next ufw enable . The right place is /etc/ufw/sysctl.conf : net / ipv4 / ip_forward = 1 net / ipv6 / conf / default / forwarding = 1 net / ipv6 / conf / all / forwarding = 1 Then check the effective value, not the file you just edited: sysctl net.ipv4.ip_forward 2. Forwarding, which is not the same as ingress Targeted, and the one to prefer: sudo ufw route allow in on wg0 out on eth0 Or globally, in /etc/default/ufw : DEFAULT_FORWARD_POLICY = "ACCEPT" The second opens forwarding for every interface. It is a good ten-second diagnostic and a poor permanent configuration. 3. NAT, which UFW never adds on its own Without it, packets leave carrying their tunnel address, which nothing on the internet knows how to answer. In /etc/ufw/before.rules , at the very top , before the *filter line: *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE COMMIT Two classic mistakes here: putting this block after *filter (it is then ignored), and copying eth0 without chec
AI 资讯
Stop Fighting Your Fitness Data: Build a Serverless Warehouse with DuckDB and dbt
If you’ve ever tried to reconcile a night of sleep from an Oura Ring , a morning run from a Garmin watch, and active minutes from an Apple Watch , you know the "Dirty Data" struggle is real. Each platform has its own schema, its own definition of "active calories," and its own idiosyncratic export format. In the world of Data Engineering , this is a classic multi-source integration problem. But you don't need a massive Snowflake cluster to solve it. Today, we’re building a high-performance, serverless data pipeline to clean and normalize wearable data using DuckDB , dbt , and GitHub Actions . By leveraging a modern Serverless Data Pipeline and DuckDB's lightning-fast processing, we can turn a mess of CSVs into a structured Parquet -based personal data warehouse. The Architecture: From Chaos to Clarity Before we dive into the code, let’s look at how the data flows from your wearables to a clean, queryable state. graph TD A[Oura JSON] -->|Python Ingestion| D[(DuckDB Raw)] B[Garmin CSV] -->|Python Ingestion| D C[Apple Health XML] -->|Python Ingestion| D D --> E{dbt Models} E -->|Cleaning| F[stg_models] E -->|Normalization| G[int_health_metrics] G -->|Final Output| H[Gold Layer: Parquet Files] H --> I[Visualization / BI] subgraph GitHub Actions D E F G H end Prerequisites To follow along, you'll need: DuckDB : The "SQLite for OLAP" that makes local analytical processing insanely fast. dbt-duckdb : The adapter that lets dbt talk to DuckDB. GitHub Actions : Our free "orchestrator." Tech Stack : DuckDB, dbt, Python, Parquet. Step 1: The Ingestion Layer (Python + DuckDB) The first hurdle is getting disparate files (JSON, CSV, XML) into a unified storage format. DuckDB is magical here because it can query these files directly. We'll use a simple Python script to load these into a local .duckdb file. import duckdb def ingest_raw_data (): # Initialize the database con = duckdb . connect ( ' health_data.duckdb ' ) # Ingest Garmin CSV con . execute ( """ CREATE TABLE raw_garmin
AI 资讯
A Dead PID Held My Lock for 2 Hours: One Missing Line, Zero Output, exit 0 Every Time
For 30 straight days as a college student earning ¥100k/month, I posted to Instagram by hand, and then I burned out and stopped. Today the same job runs on a Claude Code autonomous environment, I touch nothing, and it holds up ¥1.2M/month in revenue. Except for the two hours when it quietly stopped: three consecutive launchd runs, zero pieces of content generated, last exit=0 every single time, and not one alert. The cause was a process that had already been killed, holding a lock file nobody would take away from it. Why this setup works From "doing the work" to "building the environment" The problem with updating social media by hand is that it burns willpower. No matter how motivated you are, sleep, health, and mood all fluctuate. During the period when I was laid off and my income went to zero, I had no mental slack for posting at all. The autonomous environment I spent six months building with Claude Code runs regardless of my emotional state. launchd calls a script, the script generates content with claude -p (MAX plan quota; paid APIs are off-limits), the output is queued for auto-posting, and it goes out to Instagram every day at 19:30. As long as this machinery keeps working, ¥1.2M/month in sales holds up without me lifting a finger. The mental model I want to hand you A lot of people think "automation = writing scripts," and that's only half right. A script is correct at the moment you write it. Given time, external dependencies break, processes die for reasons you didn't anticipate, and lock files turn into debris that blocks every future run. An autonomous environment that actually works is one that assumes breakage and carries a layer that repairs it. The lock story here is a textbook case. ~/dev/brand-404/sns/gen_feature.py is a script launched on a schedule by launchd that auto-generates Instagram feature articles. A single run takes a long time (up to three claude -p calls, plus image generation, adding up to tens of minutes), so it has a lock mechani
AI 资讯
How I wrote a Go message broker with a throughput of a million messages per second
I built HermitMQ entirely in Go. The main feature is ditching heavy wrappers like JSON in favor of a custom 29 byte binary protocol. Additionally, data transmission over the network uses a direct file to socket copy mechanism. I will go into detail about the architecture, data storage approaches, benchmark numbers, and show how it is implemented in code. The full source code for the HermitMQ project is available on GitHub: https://github.com/ekhidirov/hermitmq The problem with standard brokers and the cost of serialization When the message counter exceeds hundreds of thousands per second, the main problem for a Go developer is the garbage collector. If every message is parsed via standard JSON, the application starts allocating a massive number of small objects in memory. The GC wakes up too frequently, eating up CPU time and causing network latency spikes. To avoid triggering the garbage collector at every turn, I completely abandoned standard serialization libraries. Every message is packed into a custom header of exactly 29 bytes. In code, the message structure looks extremely simple: type Message struct { Magic byte Timestamp uint64 Offset uint64 KeySize uint32 PayloadSize uint32 RecordCount uint32 Key [] byte Payload [] byte } The first byte is a magic number for version checking and instantly discarding bad packets. Next come 8 bytes for the timestamp in nanoseconds and 8 bytes for the offset, which the broker fills in itself to maintain message order. Then come the key and payload sizes, 4 bytes each. Finally, 4 bytes are reserved for the record count to support batching. The broker reads the stream using the binary package and reuses buffers via sync.Pool. As a result, under standard loads, we achieve practically zero memory allocation. Being honest about allocations and plans for zero serialization To be completely honest: although the broker is incredibly frugal under standard loads, a memory management compromise still remains. An absolute victory over al
开源项目
.NET 10 dotnet tool exec: Pin the Version and Feed in CI
A CI step that says dotnet tool exec Some.Tool looks isolated, but it is not fully reproducible. Without a version, the command can resolve the latest package from the configured feeds. Machine-level NuGet settings can also change which feeds participate. I use .NET 10 dotnet tool exec with an exact @version and an explicit feed policy when I want one-shot tooling without a global install or a committed tool manifest. The command is stable from the .NET 10.0.100 SDK onward. Microsoft describes it as a temporary invocation: the package is downloaded to the NuGet cache, executed, and left out of PATH . That is convenient for CI, but temporary installation does not automatically mean deterministic selection. Why .NET 10 dotnet tool exec can drift The official command reference documents three useful selection modes: Some.Tool can resolve the latest version when no local manifest supplies one. Some.Tool@2.* stays on a major version, but still floats within that range. Some.Tool@2.4.1 requests one exact package version. For CI, I prefer the third form. A new tool release should arrive through a reviewed change, not because the next clean runner happened to restore later. The feed is a separate input. --add-source adds another source, and NuGet can query feeds in parallel. If the same package and version exists on more than one feed, the fastest response can win. That may be acceptable for interactive experimentation. It is a poor default for a build gate. .NET 10 is currently an active LTS channel . I still pin the SDK used by CI as well, because a package pin controls the tool package, not the CLI that resolves and launches it. Pin the version and feed together For a repository policy, I give dotnet tool exec a checked-in NuGet.Config . This sample uses a generated local feed, so it needs no credentials or external package call: <?xml version="1.0" encoding="utf-8"?> <configuration> <config> <add key= "globalPackagesFolder" value= "./artifacts/global-packages" /> </conf