{"id":49312363,"url":"https://github.com/pinealctx/x","last_synced_at":"2026-04-26T13:31:14.786Z","repository":{"id":349115861,"uuid":"1200183083","full_name":"pinealctx/x","owner":"pinealctx","description":"Go common base extend libary","archived":false,"fork":false,"pushed_at":"2026-04-15T14:31:23.000Z","size":252,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-15T16:10:49.884Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pinealctx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-03T05:57:38.000Z","updated_at":"2026-04-15T14:28:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pinealctx/x","commit_stats":null,"previous_names":["pinealctx/x"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/pinealctx/x","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinealctx%2Fx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinealctx%2Fx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinealctx%2Fx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinealctx%2Fx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pinealctx","download_url":"https://codeload.github.com/pinealctx/x/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinealctx%2Fx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32299628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-26T13:31:11.407Z","updated_at":"2026-04-26T13:31:14.778Z","avatar_url":"https://github.com/pinealctx.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# x\n\nGeneric extension libraries for Go. Minimal external dependencies, generics-driven.\n\n```\ngo get github.com/pinealctx/x\n```\n\nRequires Go 1.26+.\n\n## Packages\n\n- [errorx](#errorx) — coded errors and domain-isolated sentinels\n- [panicx](#panicx) — panic recovery with stack capture\n- [syncx](#syncx) — concurrent primitives and patterns\n- [ds](#ds) — generic data structures\n- [retryx](#retryx) — retry with composable backoff\n- [ctxv](#ctxv) — type-safe context values\n- [handlerx](#handlerx) — generic middleware chain for RPC handlers\n- [pipeline](#pipeline) — declarative step-execution graph\n\n---\n\n## errorx\n\nTyped error codes and phantom-type sentinel errors.\n\n```go\n// Define error codes per domain\ntype Code int\nconst (\n    CodeNotFound Code = iota + 1\n    CodeUnauthorized\n)\n\n// Leaf error\nerr := errorx.New(CodeNotFound, \"user not found\")\n\n// Wrapped error\nwrapped := errorx.Wrap(err, CodeUnauthorized, \"access denied\")\n\n// Chain-aware code query\nerrorx.IsCode(wrapped, CodeUnauthorized) // true — checks top node only\nerrorx.ContainsCode(wrapped, CodeNotFound) // true — traverses full chain\n```\n\n```go\n// Domain-isolated sentinels (phantom type prevents cross-domain errors.Is)\ntype myDomain struct{}\nvar ErrTimeout = errorx.NewSentinel[myDomain](\"timeout\")\n\nerrors.Is(ErrTimeout, ErrTimeout) // true\n```\n\nAlso: `Newf`, `Wrapf` (format variants), `NewSentinelf`.\n\n---\n\n## panicx\n\nPanic recovery that captures the stack trace as a structured `*PanicError`.\n\n```go\n// Recover inside a goroutine\ndefer func() {\n    if r := recover(); r != nil {\n        err := panicx.NewPanicError(r)\n        log.Printf(\"panic: %v\\nstack:\\n  %s\", err, strings.Join(err.Stack(), \"\\n  \"))\n    }\n}()\n\n// Adjust stack skip for wrapper functions\nerr := panicx.NewPanicErrorSkip(r, 2)\n```\n\nUse `errors.Is(err, panicx.ErrPanic)` to check whether an error originated from a panic.\n\n---\n\n## syncx\n\n### KeyedMutex / KeyedLocker\n\nPer-key locking with automatic cleanup via reference counting.\n\n```go\nkm := syncx.NewKeyedMutex[string]()\nunlock := km.Lock(\"user:42\")\ndefer unlock()\n\nkl := syncx.NewKeyedLocker[string]()\nunlock := kl.RLock(\"resource:1\")\ndefer unlock()\n```\n\nAlso: `Len()` on both types.\n\n### BlockingQueue\n\nContext-aware blocking queue with close semantics.\n\n```go\nq := syncx.NewBlockingQueue[int](64)\n\n// producer\nq.Push(ctx, 42)\n\n// consumer\nv, err := q.Pop(ctx)\n\n// graceful shutdown\nq.Close() // drain remaining items\nq.CloseNow() // discard remaining items\n```\n\nAlso: `TryPush`, `TryPop` (non-blocking), `Peek`, `Len`.\n\n### RingQueue\n\nFixed-capacity queue that evicts the oldest item when full.\n\n```go\nq := syncx.NewRingQueue[string](8)\nq.Push(ctx, \"msg\")\nv, err := q.Pop(ctx)\n\n// returns evicted value when full\nold, ok := q.PushEvict(\"overflow\")\n```\n\nAlso: `TryPop` (non-blocking), `Peek`, `Len`, `Close`, `CloseNow`.\n\n### ReadThrough\n\nCache-aside with per-key stampede protection.\n\n```go\nrt := syncx.NewReadThrough[string, User](cache, func(ctx context.Context, key string) (User, error) {\n    return db.GetUser(ctx, key)\n})\n\nuser, err := rt.Get(ctx, \"user:42\")\n```\n\n### Pool\n\nType-safe wrapper around `sync.Pool`.\n\n```go\np := syncx.NewPool(func() *bytes.Buffer { return new(bytes.Buffer) },\n    func(b *bytes.Buffer) { b.Reset() })\n\nbuf := p.Get()\ndefer p.Put(buf)\n```\n\n### Dispatcher\n\nRoutes keyed work to a fixed set of goroutines by hash — preserves per-key ordering.\n\n```go\nd := syncx.NewDispatcher[string, int](8, func(key string, val int) error {\n    // always called on the same goroutine for the same key\n    return nil\n})\ndefer d.Close()\nd.Submit(\"user:42\", 1)\n```\n\nOptions: `WithBuffer(n)` to set per-slot buffer, `WithOnError(fn)` for error callback.\nAlso: `TrySubmit` (non-blocking).\n\n### SingleFlight\n\nDeduplicates concurrent calls for the same key.\n\n```go\nsf := syncx.NewSingleFlight[string, *Data]()\nresult, shared, err := sf.Do(\"key\", func() (*Data, error) {\n    return fetchData()\n})\nsf.Forget(\"key\") // evict cached result\n```\n\n### Group\n\nCollects results from concurrent goroutines in submission order.\n\n```go\ng := syncx.NewGroup[int](0)\ng.Go(func() (int, error) { return compute1() })\ng.Go(func() (int, error) { return compute2() })\nresults := g.Wait() // []Result[int] in submission order\n```\n\n### Race\n\nReturns the first successful result; if all fail, returns the last error.\n\n```go\nval, err := syncx.Race(ctx,\n    func(ctx context.Context) (string, error) { return fetchFromPrimary(ctx) },\n    func(ctx context.Context) (string, error) { return fetchFromFallback(ctx) },\n)\n```\n\n---\n\n## ds\n\nNon-concurrent-safe generic containers. Use external synchronization when sharing across goroutines.\n\n### OrderedMap\n\nInsertion-ordered map with O(1) access and zero-allocation iteration.\n\n```go\nm := ds.NewOrderedMap[string, int]()\nm.Set(\"a\", 1)\nm.Set(\"b\", 2)\nfor k, v := range m.All() {\n    fmt.Println(k, v) // a 1, b 2 — insertion order\n}\n```\n\nAlso: `NewOrderedMapWithCapacity`, `Get`, `Has`, `Delete`, `Backward`, `Keys`, `Values`, `Clone`, `Len`, `Clear`.\n\n### Set\n\nSet algebra and relation checks.\n\n```go\na := ds.NewSet(\"a\", \"b\", \"c\")\nb := ds.NewSet(\"b\", \"c\", \"d\")\n\na.Union(b)       // {a, b, c, d}\na.Intersect(b)   // {b, c}\na.Difference(b)  // {a}\na.IsSubset(b)    // false\n```\n\nAlso: `NewSetWithCapacity`, `Add`, `Remove`, `Has`, `SymmetricDifference`, `Equal`, `IsSuperset`, `ToSlice`, `Clone`, `Len`, `Clear`.\n\n### BiMap\n\nBidirectional O(1) lookup.\n\n```go\nm := ds.NewBiMap[string, int]()\nm.Set(\"one\", 1)\nm.GetByKey(\"one\")  // 1, true\nm.GetByValue(1)    // \"one\", true\n```\n\nAlso: `NewBiMapWithCapacity`, `DeleteByKey`, `DeleteByValue`, `Keys`, `Values`, `Clone`, `Len`, `Clear`.\n\n### Stack\n\nLIFO stack.\n\n```go\ns := ds.NewStack[int]()\ns.Push(1)\ns.Push(2)\nv, _ := s.Pop() // 2\n```\n\nAlso: `NewStackWithCapacity`, `Peek`, `Clone`, `Len`, `Clear`.\n\n### Heap\n\nBinary heap with custom comparator.\n\n```go\nh := ds.NewMinHeap[int]()   // min-heap\nh := ds.NewMaxHeap[int]()   // max-heap\nh := ds.NewHeap(func(a, b int) int { return a - b }) // custom\nh.Push(3, 1, 2)\nv, _ := h.Pop() // 1 (min)\n```\n\nAlso: `NewHeapFrom` (initialize from slice), `Peek`, `Drain` (pop-all iterator), `Clone`, `Len`, `Clear`.\n\n### SortedMap\n\nOrdered map combining O(1) key lookup with O(log n) sorted iteration. Backed by `tidwall/btree`.\n\n```go\ntype Item struct {\n    ID    int\n    Score float64\n}\n\nm := ds.NewSortedMap[int, Item](\n    func(v Item) int { return v.ID },    // key extraction\n    func(a, b Item) bool { return a.Score \u003c b.Score }, // sort order\n)\nm.Set(Item{ID: 1, Score: 3.0})\nm.Set(Item{ID: 2, Score: 1.0})\nm.Set(Item{ID: 3, Score: 2.0})\n\nfor v := range m.Ascend() {\n    fmt.Println(v.ID, v.Score) // 2 1.0, 3 2.0, 1 3.0\n}\n```\n\nAlso: `Get`, `Has`, `Delete`, `AscendFrom`, `AscendAfter`, `Descend`, `DescendFrom`, `DescendBefore`, `Len`, `Clear`.\n\n---\n\n## retryx\n\nGeneric retry with composable backoff strategies.\n\n```go\nresult, err := retryx.Do(ctx, func() (string, error) {\n    return callAPI()\n},\n    retryx.Attempts(3),\n    retryx.Backoff(\n        retryx.WithJitter(\n            retryx.NewExponential(100*time.Millisecond, 2.0),\n            0.2,\n        ),\n    ),\n    retryx.RetryIf(func(err error) bool {\n        return errors.Is(err, ErrTransient)\n    }),\n    retryx.OnRetry(func(attempt int, err error) {\n        log.Printf(\"attempt %d failed: %v\", attempt, err)\n    }),\n)\n```\n\nBackoff strategies: `NewExponential`, `NewFixed`. Wrappers: `WithJitter`, `WithMaxWait`.\n\n---\n\n## ctxv\n\nType-safe context values without type assertions.\n\n```go\nvar requestIDKey = ctxv.NewKey[string](\"requestID\")\n\n// store\nctx = requestIDKey.WithValue(ctx, \"req-123\")\n\n// retrieve\nid, ok := requestIDKey.Value(ctx)       // \"req-123\", true\nid   := requestIDKey.MustValue(ctx)     // panics if missing\n```\n\n---\n\n## handlerx\n\nFramework-agnostic generic middleware chain for RPC handlers.\n\n```go\n// Define handler and interceptors\nh := func(ctx context.Context, req MyRequest) (MyResponse, error) {\n    return MyResponse{Result: \"ok\"}, nil\n}\n\n// Chain interceptors (outermost first)\nh = handlerx.Chain(h,\n    handlerx.WithTimeout[MyRequest, MyResponse](5*time.Second),\n    handlerx.WithRecovery[MyRequest, MyResponse](),\n)\n\n// Execute\nresp, err := h(ctx, req)\n```\n\n---\n\n## pipeline\n\nDeclarative step-execution graph: sequential (Then), concurrent all-must-succeed (Parallel), and concurrent first-success (Race).\n\n```go\ntype state struct {\n    Req  *Request\n    Data *Data\n}\n\nerr := pipeline.New[state]().\n    Then(\"validate\", func(ctx context.Context, s *state) error {\n        return validate(s.Req)\n    }).\n    Parallel(\"fetch\", fetchA, fetchB).\n    Then(\"save\", func(ctx context.Context, s *state) error {\n        return save(ctx, s.Data)\n    }).\n    Run(ctx, \u0026state{Req: req})\n```\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpinealctx%2Fx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpinealctx%2Fx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpinealctx%2Fx/lists"}