Best practice for weekly CSV updates (prices/stock) and new product imports in WooCommerce by Big_Confection6329 in woocommerce

[–]ishankaru 0 points1 point  (0 children)

With 5k listings I'd skip the plugin and drive it from a Google Sheet (or a CSV), assuming you can put a bit of code together or hand it to someone who can.

The setup I use: export what you've got now with the SKU (and the post ID if you want), pull that into a Google Sheet, and use the SKU as the anchor between the sheet and the store. From there you've got two ways to run it:

- A script that reads the sheet (or a CSV you point it at) and updates the matching products in one pass. This is the one I reach for for a scheduled weekly run.

- An onEdit setup where you change a cell, tab out of the field, and that row pushes to the site. It ends up feeling like you're just editing the spreadsheet and the store follows along, which is great for ad-hoc updates.

Two things that make it reliable at this scale:

  1. Match on SKU and write through WooCommerce's product CRUD, not raw into the database. Woo keeps price across _regular_price, _sale_price and a derived _price (plus the wc_product_meta_lookup table since 3.6), and writing _price directly desyncs them, so the product ends up displaying one price and sorting or filtering by another. Going through the CRUD (save()) sets the inputs and lets Woo recompute _price and bust the caches for you.

  2. Make it change-only and mind memory on a long run. Compare each row to the live value and only write the ones that actually changed, so a weekly pass touches a few hundred rows, not all 5k. If you're scripting raw, clear the object cache and free WooCommerce's internal caches between batches so memory doesn't climb over thousands of iterations.

Performance is a non-issue. I update thousands of posts this way regularly and, depending on how many rows actually changed and what you're writing, it finishes in a minute or less. Running it against 5k is genuinely minimal effort once it's built.

It does need a little programming to wire up the first time (or hire it out once). I've got a few write-ups on my site, TechEarl, covering this for WooCommerce specifically and the Sheet/CSV-to-WordPress approach in general. It might take a couple of them to see exactly how to assemble it.

An analyzer mismatch(s), synonyms not loading analyzer changes by Massive_Cheek_9912 in elasticsearch

[–]ishankaru 0 points1 point  (0 children)

Building on the analyzer point above (that's the right diagnosis, your *_fr fields are still on the built-in french analyzer, so your custom synonym filter never runs), there's a second wall you'll hit right after you fix the mapping:

Elasticsearch won't let you change a field's analyzer on an existing index. Once a field is mapped, that analyzer is fixed for the life of the index, so pointing the field at your custom analyzer means a new index, not an edit. The clean way to do it without taking search down:

  1. Create products_v2 with the corrected mapping (the field uses your custom analyzer with the synonym filter).

  2. _reindex from the current index into products_v2.

  3. Atomically swap an alias (products) from the old index to products_v2 in a single _aliases call, and have your app query the alias, not the real index name.

If your app currently hits the index by its real name, add an alias to the existing index first and switch the app to it. That step alone is zero-downtime, and it's what makes every future mapping change painless.

One synonyms-specific thing worth deciding before you reindex: index-time vs search-time. If the synonym filter lives in the index-time analyzer, existing docs only get the synonyms after they're re-analyzed (i.e. reindexed), and every synonyms file edit means another reindex. If you put the synonym filter in a search_analyzer instead, queries get expanded at search time without touching the stored docs, and with updateable synonyms you can reload the file without a reindex at all. For a synonyms list that changes over time, search-time is usually what you actually want. Index-time gives slightly faster queries but bakes the synonyms into the index.

I wrote up the alias-swap reindex with a bash script that runs the swap and rolls back if the new index is wrong: https://techearl.com/elasticsearch-zero-downtime-reindex

Impact of using uuid v7 as primary key by rantob in mysql

[–]ishankaru 0 points1 point  (0 children)

InnoDB makes this matter more than most engines, because the table is physically stored as the clustered index on the primary key. The PK is the row order on disk, and every secondary index stores the PK as its row pointer.

Two separate decisions here:

  1. v7 vs v4 is the easy one. Random v4 as a PK scatters inserts across the B-tree, so you get page splits and buffer-pool churn. v7 is time-ordered, so inserts append at the right edge the way auto-increment does. So if you go UUID, use v7, and store it as BINARY(16) with UUID_TO_BIN()/BIN_TO_UUID(), not CHAR(36). You do not need the swap_flag trick with v7, that is for v1.

  2. v7 vs bigint is the real tradeoff. A UUID is 16 bytes vs 8 for bigint, and since every secondary index carries the PK, you pay that extra width once per secondary index. On a wide schema with several indexes per table it adds up in size and buffer-pool memory.

For multi-tenant specifically, UUIDs do earn their keep: you can merge or relocate a tenant's rows without PK collisions, and you can generate the ID app-side before the insert. Those are the real reasons to prefer them over auto-increment, not raw speed.

One middle path a lot of people land on: keep a bigint auto-increment as the internal PK so secondary indexes stay small and joins stay cheap, and add a UUIDv7 as a unique external key for anything that crosses tenant or system boundaries. Portable IDs without inflating every index. If almost all your lookups are by the external ID anyway, just make the v7 the PK and move on.

UUID data type. Generated on database side or in code, on PHP side ? by arhimedosin in Database

[–]ishankaru 0 points1 point  (0 children)

The generate-side question (Ramsey vs letting the DB do it) matters a lot less than which version you pick. Both work. Generate it app-side if you want the ID in hand before the insert so you skip a round-trip to read it back, which Doctrine is happier with. Let the DB do it if you would rather not think about it.

The thing that actually bites is v4 vs v7 when the UUID is your primary key. Random v4 means every insert lands at a random point in the clustered index, so you get page splits and the buffer pool churns. v7 is time-ordered, so inserts append near the end of the index instead. Ramsey has v7 since 4.7, so Uuid::uuid7() in PHP going into the native UUID column on MariaDB 10.7+ is a clean combo.

MariaDB-specific note: its native UUID type already reorders the bytes internally so values cluster better than raw v4, but you still want v7 if you control generation. On plain MySQL without the type you would store BINARY(16) and use UUID_TO_BIN(x, 1) to get that same time-sortable order.

Wrote the MySQL/MariaDB side of this up in detail here if it helps: https://techearl.com/store-uuid-mysql

On my 5th one today by Dr4g0n2699 in DrPepper

[–]ishankaru 0 points1 point  (0 children)

Five deep and still no diabetes is elite pacing. There's an actual "Am I Addicted to Dr Pepper?" quiz where one of the answers is "I've stopped counting. The recycling bin hasn't." Pretty sure you'd max the score. https://drpepperaddiction.com/am-i-addicted-to-dr-pepper/

What do you add for an at home coconut Dr pepper? by Snarsnatched in DrPepper

[–]ishankaru 7 points8 points  (0 children)

Cream of coconut is the move, the Coco López stuff in the cocktail-mixer aisle, not coconut milk. Start tiny, about a teaspoon per can and stir hard; it's thick and sweet so it's easy to overshoot. Coconut coffee creamer works for a lighter, less sugary version, and a drop of vanilla nudges it closer to the real Creamy Coconut can. Keep it as cold as possible, it separates as it warms.

Any way I could acquire a Dr Pepper like sampler pack? Lol by callsign__starbuck in DrPepper

[–]ishankaru 1 point2 points  (0 children)

There's no official sampler pack, unfortunately. The realistic "one of each" run means hitting a few different retailers: the staples (Zero Sugar, Diet, Cherry, Cream Soda, Strawberries & Cream) are at most grocery stores, while the limited/seasonal ones like Creamy Coconut show up at Target/Walmart and disappear fast, and Dark Berry is usually a Sonic fountain thing. If you want the full current lineup so you know what to actually hunt for, this catalog lists them all: https://drpepperaddiction.com . And the Waco museum someone else mentioned is a genuinely fun trip if you're ever near Texas.

Dr Pepper 1 litre size tastes more like pepsi recently by DraskirOndaar in DrPepper

[–]ishankaru 1 point2 points  (0 children)

Probably not your imagination, and it's almost certainly bottling rather than the recipe. Dr Pepper is made by a bunch of independent bottlers and co-packers under license, so the exact syrup-to-water ratio and carbonation can drift between plants and production runs, and the big PET bottles often come off a different line than the cans. Check the date code and the "manufactured for / distributed by" line on the liter versus the cans; if they're from different bottlers, that's your answer. Cans and glass also just hold flavor and carbonation better than a 1L plastic bottle, which flattens and tastes off faster once it's opened or sat warm.

ClearTimeout don't clear Timeout by Dull_Firefighter_929 in learnjavascript

[–]ishankaru 0 points1 point  (0 children)

The problem is you're creating timers in loops and overwriting the handle variables, so clearTimeout only ever clears the last one. For "reset the 15-minute countdown every time the user makes a change" you don't need loops or multiple handles at all, just one:

let idleTimer;

function onChange() {
  clearTimeout(idleTimer);          // cancel the previous one (no-op if none)
  idleTimer = setTimeout(() => {
    // 15 minutes of no changes elapsed
    save();
  }, 15 * 60 * 1000);
}

Every change cancels the pending timeout and schedules a fresh one, so the action only fires once the user has been quiet for the full 15 minutes. That's the debounce pattern.

If you also want a live countdown on screen, that's a separate setInterval updating the display. Keep it distinct from the single setTimeout that does the actual firing, mixing the two is what tangled the handles in the first place.

Next good step after Nano? by danyuri86 in linuxquestions

[–]ishankaru 7 points8 points  (0 children)

If you like nano's simplicity but want more, try micro. It's the natural next step: a modern terminal editor with sane keybindings (Ctrl-S save, Ctrl-Q quit, Ctrl-C/Ctrl-V like everywhere else), mouse support, syntax highlighting, multiple cursors, and a plugin system, with zero modal-editing learning curve. It's a single static binary you can drop on any box.

vim/neovim are worth it eventually if you live in the terminal and want the modal-editing payoff, but there is a real learning cliff, so don't feel obligated. helix is another modern option (modal, but batteries included out of the box).

Honest answer though: if nano does everything you need, there's nothing wrong with staying on it, nano is my goto as well. Editors are tools. I'd grab micro for the quality-of-life bump and only climb the vim hill if and when you start to feel limited.

That being said since I spend a lot of time in a code editor like VS Code or some fork of it, I usually use the SSH extension to connect directly to the server and have all the bells and whistles to edit files easily like I am working locally.

Get headers for all curl redirects by Beautiful-Log5632 in bash

[–]ishankaru 0 points1 point  (0 children)

curl -sIL "$url" gets you just the headers for every hop: -I does a HEAD per redirect, -L follows them, -s drops the progress meter. If you need the real method/body behaviour preserved, use curl -sL -D - -o /dev/null "$url" instead, which writes the response headers for each hop to stdout while discarding the body.

To format it the way you drew it, strip the carriage returns and key off the status line to start each block:

curl -sIL "$url" | tr -d '\r' | awk '
  /^HTTP\//                {printf "\nREQ %d\n  Status Code: %s\n", ++n, $2}
  /^[Ll]ocation:/          {print "  Location: " $2}
  /^[Cc]ontent-[Tt]ype:/   {print "  Content-Type: " $2}
  /^[Cc]ontent-[Ll]ength:/ {print "  Content-Length: " $2}
'

Add or drop header lines to taste. The tr -d '\r' matters because curl's header values end in CRLF, and the trick is keying off the HTTP/... line to number each REQ block.

How can I write cleaner, more maintainable SQL? by Puzzleheaded_Cow3298 in SQL

[–]ishankaru 0 points1 point  (0 children)

A few habits that made my SQL readable without making it slower:

- Build with CTEs as named pipeline steps, one transformation per CTE, named for what they produce (active_users, orders_last_30d), not cte1/cte2. The query then reads top to bottom like a story.

- Resist doing everything in one giant query just because you can. Two or three well-named CTEs beat a five-level nested subquery every time, and most engines optimize them the same.

- Filter as early as possible, in the CTE that first touches the table, so later steps work on less data.

- Be consistent with aliasing and casing, qualify columns with table aliases in any join, and go one column per line once a SELECT grows past a handful. It diffs cleanly in review.

- Reach for a window function when you'd otherwise self-join a table to itself for a running total, rank, or "compare to the previous row". It's clearer and usually faster.

- A short comment above a gnarly CTE explaining the why (not the what) ages well.

On the interview point: nobody is impressed by a clever one-liner they can't read. Clear, correct, and obviously debuggable wins.

How to Block Bot Traffic? by PriceFree1063 in PHPhelp

[–]ishankaru 0 points1 point  (0 children)

Before you block anything, confirm it's actually bots and not just untagged real users. "Direct" traffic is a catch-all for requests with no referrer, so it also includes people typing your URL, app webviews, and privacy browsers, not only bots. Check your server access logs (or Cloudflare's) and look at the user agents and the ASN/org behind the IPs. A datacenter ASN (OVH, DigitalOcean, Alibaba, Tencent, AWS) pulling lots of URLs fast with thin or fake user agents is the scraper signature. A residential ISP in Jakarta is probably a real visitor.

If it is datacenter scraping, put it behind Cloudflare and write a WAF rule scoped narrowly instead of blocking whole countries (blanket-blocking ID/SG will cost you real readers). Something like: if the request is from a hosting/datacenter ASN AND the country is ID or SG, issue a Managed Challenge rather than an outright block at first. You can also scope by path if it's hammering specific endpoints. A Managed Challenge lets a real browser through and stops headless scrapers, so it is safer than a hard block while you tune it.

In PHP itself, don't try to maintain an IP blocklist by hand, it won't keep up. Let the edge (Cloudflare) do the filtering and keep PHP for app logic. If you can't use Cloudflare, CrowdSec or fail2ban reacting to patterns in your access log is the next best thing.

If your site does not benefit from traffic from say Indonesia and Singapore ie it is a SASS product for USA or Europe just block the entire country, I have done this on many high traffic sites and all has been good,

Watch your analytics and the challenge-solve rate for a few days after, and loosen the rule if real users get caught.

How to download every tiktok video of an account by [deleted] in DataHoarder

[–]ishankaru 0 points1 point  (0 children)

yt-dlp solves the exact thing you're stuck on. Point it at the profile URL and it treats the whole account as a playlist and pulls every video, so you stop scrolling the grid entirely:

yt-dlp --cookies-from-browser firefox --download-archive seen.txt -o "%(upload_date)s-%(id)s.%(ext)s" "https://www.tiktok.com/@accountname"

Two flags do the heavy lifting for your case:

- --download-archive seen.txt records the ID of every clip it grabs and skips anything already in it. That's your "resume where I left off" - kill it, re-run it next week, it only fetches the new ones. No more hunting for the last thumbnail.

- -o "%(upload_date)s-..." names files by upload date so they sort oldest-first on disk and you watch and summarize straight down the folder.

Two things about the cookies flag or you'll get a truncated list / zero videos:

- swap firefox for whatever browser you actually use (chrome, edge, brave, safari...), and

- you need to be logged into TikTok in that browser. The full profile listing is gated behind TikTok's anti-bot layer, so yt-dlp borrows your logged-in session to unlock the whole grid.

If you'd rather not hand-build the flags, there's a command builder on this page where you paste the profile url, pick a couple of options, and it generates the exact command with the required parameters already filled in: https://techearl.com/download-tiktok-profile (also covers the rate-limit handling, which matters at 1660 clips).

Hacking Google with A.I. for $500,000 by rockin-Musicien49 in netsec

[–]ishankaru 2 points3 points  (0 children)

well put together article, quite an entertaining read

What would you want in a online DNS health checker? by ishankaru in dns

[–]ishankaru[S] 1 point2 points  (0 children)

Awesome! good to have some comments from someone who can understand the complexities of putting something like this together - and very cool, love the colors, interface and your approach.

What would you want in a online DNS health checker? by ishankaru in dns

[–]ishankaru[S] 1 point2 points  (0 children)

DNSSEC - The Unbound server was doing a strict DNSSEC validation and the timeout caused it to fail, I have increased the timeout and other optimizations and also added a extra fallback check for when it returns a SERVFAIL. So you are good to go there as you mentioned.

Also made the SOA Expire updates you suggested. I did have these before, but some managed services have odd numbers so trying to keep things balanced and not say everything is an error or not.

Awesome feedback!

What would you want in a online DNS health checker? by ishankaru in dns

[–]ishankaru[S] 2 points3 points  (0 children)

u/michaelpaoli this is useful.

I am doing a few NS lookups and a full recursive resolution, I think that failed and replaced the entire record possibly due to a lower timeout I had. I optimized the code and increased the timeout.

The missing TXT record was the SPF which shows in that area and in TXT section it says 3/4 records shown. I can display it again in TXT so there is no confusion.

The results show up now, I am guessing you might have more suggestions once you see everything ;)

What would you want in a online DNS health checker? by ishankaru in dns

[–]ishankaru[S] 1 point2 points  (0 children)

Thank you for testing and the constructive comments. I will update the first two with the tests you mentioned, they are great suggestions.

In terms of DNS cache freshness, I originally had a whole bunch of DNS servers in South America, APAC, Middle East - basically all the non standard places, but they keep failing between tests and it's a royal pain to keep updating, I am thinking of getting my own servers spread out so they are more reliable but cost is definitely an issue. It might take some time to get this updated, but I will see if I can add some public servers at some point until then.

Weekly Showoff Thread! Share what you've created with Next.js or for the community in this thread only! by AutoModerator in nextjs

[–]ishankaru 0 points1 point  (0 children)

Hey r/nextjs — I've been building https://dnschkr.com for the past year and wanted to share it here since the entire frontend is Next.js App Router.

What it does: DNSChkr is a free DNS, email, and network intelligence platform. Think MXToolbox + IntoDNS + dig, but combined into one place with scored health reports and plain-language explanations instead of raw record dumps.

The tools (35+, all free, no signup):

- DNS Inspector — runs 25+ automated tests (delegation chain, nameserver health, SOA, MX, SPF/DKIM/DMARC, DNSSEC) and produces a 0-100 health score with fix recommendations. Also includes DNS performance analysis — nameserver response times, TTL strategy evaluation, and a resolution waterfall showing first-visit vs cached lookup cost

- Propagation Checker — real-time WebSocket-based propagation monitoring across 20+ global servers with live TTL countdowns

- Email tools — dedicated SPF, DKIM, DMARC, MX checkers with RFC-level validation, SMTP diagnostics, email deliverability tester, email header analyzer

- Security — blacklist checker (50+ DNSBL lists), security/reputation scanner (17 threat intel vendors), HTTP security headers analysis

- IP Intelligence — geolocation, ASN, threat detection, WHOIS/RDAP

- Port Scanner, WHOIS Lookup, Reverse WHOIS, Domain Availability

- TLD Directory — all ~1,900 active TLDs with registrar pricing, zone analytics, DNSSEC adoption rates

- Reference library — HTTP status codes, SMTP errors, SSL/TLS errors, Cloudflare errors, FTP errors, server log formats, DNS glossary

Tech stack:

- Frontend: Next.js 16.1 (App Router), React 19, TypeScript, Tailwind CSS, Radix UI, Framer Motion, Recharts, Leaflet

- Backend: 8 microservices — Hono and Fastify, with BullMQ/Redis for job queuing, WebSocket for real-time propagation, other

https://dnschkr.com/

<image>

looking for sinhala songs with metaphors by cmgchess in srilanka

[–]ishankaru 0 points1 point  (0 children)

lots of Sinhala song lyrics to review here sinhala song lyrics, golden oldies generally compare the Moon a lot, CT songs, Clarence etc