Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166]) by code.netlandish.com (Postfix) with ESMTP id 07A00162 for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 21 May 2025 18:55:02 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.219.169; helo=mail-yb1-f169.google.com; envelope-from=peter@netlandish.com; receiver= Authentication-Results: mail.netlandish.com; dkim=pass (1024-bit key; unprotected) header.d=netlandish.com header.i=@netlandish.com header.b=mc8KbCTt Received: from mail-yb1-f169.google.com (mail-yb1-f169.google.com [209.85.219.169]) by mail.netlandish.com (Postfix) with ESMTP id B8C241D6462 for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 21 May 2025 18:55:20 +0000 (UTC) Received: by mail-yb1-f169.google.com with SMTP id 3f1490d57ef6-e7d664bcd34so620497276.0 for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 21 May 2025 11:55:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netlandish.com; s=google; t=1747853719; x=1748458519; darn=lists.code.netlandish.com; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=nD3Atxlpdy7FHibkLQbahFNunHhnXea4XqREvXQWkD4=; b=mc8KbCTtOmlwJHPbCUTW+QsRSST3qaYUw8KLM6sFRGxYqJA193ouWsE+AYaU1ceexr WcPLnloAmLQD93iq3cuWMNmxs0f04Md9aU9AHVtTX4RFCzoYJVZKrhJFeAsZts+bmu4a //p/+jSpXgLUfa01507IpcWqDPt4WnIEtZXgo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747853719; x=1748458519; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=nD3Atxlpdy7FHibkLQbahFNunHhnXea4XqREvXQWkD4=; b=gXK54EgHZnh7SA6mHm3XbB5ToQxO2dii1odpmgYmJSNdUzROWGZTtYn27uESvlCYyh +r1vryOCtPR2r+IuSz8s4dxZZ98dFg7cuWBu/6F469vFqxxeGKlztZMUGC6CHwTc+2N6 LiVDRyMkqVPMWG0BNv+ygqfbM6jlDrVr+ju1r/FGJJgx4zQTwD4EcFPqLm3rBN6Er4ZR L/+5wNWvTX7WpNRewPlnL5FVpO73j/BeGuDyEuDrp4WSe/o+HL1CqHNCUaOmqrHU5jYY uPTTb3HzdjGKd3gkcUCmxtwbs1ClbSjePJSRFAQlbw6bCGRVIf+esF/FLcRFY3lDyCtj Jttw== X-Gm-Message-State: AOJu0YyJcsklOrcL/MNBX8lrqazVPk5/sA8QqAAWBORIiygk3EwA24G4 RIp2gAEqTMPB0y/N89zkTdKS9v7i1KKoI0NsvgVaw9SqdyNw79eQE/spkai7268A4fOrfKCxTrR VtODXRlw/9TwT X-Gm-Gg: ASbGncsPzXNfXQ4f51MjHD93IgEhw2PKxuTcwMV6yEJsiXNsawdGoTnoEScqvYsP9Bj B5HF8egmdf2e7xflT6tTiUTHRB0ZpUmeX9BytABnHPQizqwhePNc3+jR1hSICB7CKhV4TqDglpT M18puhoLUGTwleAcs4sRG77xlIFyx2k4wf5LkY0Llm/0FbabWceOj12EGDg06rODEEOICjAlSZo EjAzsoWK0HBTvW72XqNxvYv1emFgRmIIp+ARFP7421NjlatpA4PRdSjhT/UTXw82VK++rzShQwB l7tPJ5fDMogWBU8D4+mPnEM0nMYoItIKKRtYusVw09eJAByVKQ== X-Google-Smtp-Source: AGHT+IFvsd1BFg5Nz2dRmjHs4urraVXT2tGVRij0hc0R1ZjXsJK9KHqkdFhgKycaCZPjOwYUzwj5og== X-Received: by 2002:a05:6902:6c17:b0:e7b:6915:de20 with SMTP id 3f1490d57ef6-e7b6a42cb6dmr26413085276.42.1747853719406; Wed, 21 May 2025 11:55:19 -0700 (PDT) Received: from localhost ([2800:e2:37f:ee6c:b36f:76e4:f6f8:a062]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-e7b6acb1ed4sm4139654276.30.2025.05.21.11.55.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 May 2025 11:55:18 -0700 (PDT) From: Peter Sanchez To: ~netlandish/links-dev@lists.code.netlandish.com Cc: Peter Sanchez Subject: [PATCH links] Update how base_url counter is updated. This is a more accurate way of dealing with this. Date: Wed, 21 May 2025 12:55:13 -0600 Message-ID: <20250521185516.12459-1-peter@netlandish.com> X-Mailer: git-send-email 2.47.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Also always update base_url counter when calling `updateLink` mutation. Found an edge case where counters were higher than they should be. Changelog-Changed: How `BaseURL.UpdateCounter` works. Now uses a subselect to set proper count Changelog-Changed: Now will alwyas call `UpdateCounter` when calling the `updateLink` mutation. This addresses a small counter bug / edge case. --- api/graph/schema.resolvers.go | 61 ++++++++++++++++++----------------- models/base_url.go | 21 ++++++------ 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index 18a5734..8bd3f3d 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -558,12 +558,9 @@ func (r *mutationResolver) AddLink(ctx context.Context, input *model.LinkInput) } } - // If the link if public, add +1 to the base url counter - if OrgLink.Visibility == models.OrgLinkVisibilityPublic { - err = BaseURL.UpdateCounter(ctx, true) - if err != nil { - return nil, err - } + err = BaseURL.UpdateCounter(ctx) + if err != nil { + return nil, err } c := server.EchoForContext(ctx) @@ -665,6 +662,8 @@ func (r *mutationResolver) UpdateLink(ctx context.Context, input *model.UpdateLi } srv := server.ForContext(ctx) + var BaseURL *models.BaseURL + // If the input has changed if input.URL != nil { if orgLink.Type == models.NoteType { @@ -673,7 +672,7 @@ func (r *mutationResolver) UpdateLink(ctx context.Context, input *model.UpdateLi WithCode(valid.ErrValidationCode) return nil, nil } - BaseURL := &models.BaseURL{ + BaseURL = &models.BaseURL{ URL: links.StripURLFragment(*input.URL), } err = BaseURL.Store(ctx) @@ -699,17 +698,13 @@ func (r *mutationResolver) UpdateLink(ctx context.Context, input *model.UpdateLi return nil, nil } else if string(*input.Visibility) == models.OrgLinkVisibilityPublic && orgLink.Type == models.NoteType { // NOTE: when making a note public we want to process its url and creata a base url obj - BaseURL := &models.BaseURL{ + BaseURL = &models.BaseURL{ URL: orgLink.URL, } err = BaseURL.Store(ctx) if err != nil { return nil, err } - err = BaseURL.UpdateCounter(ctx, true) - if err != nil { - return nil, err - } srv.QueueTask("general", core.ParseBaseURLTask(srv, BaseURL, nil)) } orgLink.Visibility = string(*input.Visibility) @@ -773,6 +768,19 @@ func (r *mutationResolver) UpdateLink(ctx context.Context, input *model.UpdateLi } } + // Update BaseURL counter + if BaseURL == nil { + BaseURL = &models.BaseURL{ID: orgLink.BaseURLID} + err := BaseURL.Load(ctx) + if err != nil { + return nil, err + } + } + err = BaseURL.UpdateCounter(ctx) + if err != nil { + return nil, err + } + c := server.EchoForContext(ctx) mdata := make(map[string]any) mdata["org_id"] = org.ID @@ -860,23 +868,20 @@ func (r *mutationResolver) DeleteLink(ctx context.Context, hash string) (*model. } deletedID := link.Hash - visibility := link.Visibility baseURLID := link.BaseURLID err = link.Delete(ctx) if err != nil { return nil, err } - // If the link if public, add +1 to the base url counter - if visibility == models.OrgLinkVisibilityPublic { - baseURL := &models.BaseURL{ID: baseURLID} - err = baseURL.Load(ctx) - if err != nil { - return nil, err - } - err = baseURL.UpdateCounter(ctx, false) - if err != nil { - return nil, err - } + + baseURL := &models.BaseURL{ID: baseURLID} + err = baseURL.Load(ctx) + if err != nil { + return nil, err + } + err = baseURL.UpdateCounter(ctx) + if err != nil { + return nil, err } c := server.EchoForContext(ctx) @@ -1001,11 +1006,9 @@ func (r *mutationResolver) AddNote(ctx context.Context, input *model.NoteInput) return nil, err } - if string(input.Visibility) == models.OrgLinkVisibilityPublic { - err = BaseURL.UpdateCounter(ctx, true) - if err != nil { - return nil, err - } + err = BaseURL.UpdateCounter(ctx) + if err != nil { + return nil, err } OrgLinkNote := &models.OrgLink{ diff --git a/models/base_url.go b/models/base_url.go index b552287..affaa04 100644 --- a/models/base_url.go +++ b/models/base_url.go @@ -220,23 +220,22 @@ func (b *BaseURL) ToLocalTZ(tz string) error { } // UpdateCounter ... -func (b *BaseURL) UpdateCounter(ctx context.Context, add bool) error { - // XXX Probably should change this to just use a subselect count(*) - op := "+" - if !add { - op = "-" - } - query := fmt.Sprintf(` +func (b *BaseURL) UpdateCounter(ctx context.Context) error { + query := ` UPDATE base_urls - SET counter = counter%s1 + SET counter = ( + SELECT count(*) + FROM org_links + WHERE base_url_id=$1 + AND visibility='PUBLIC' + ) WHERE id = $1 RETURNING (updated_on) - `, op) - err := database.WithTx(ctx, nil, func(tx *sql.Tx) error { + ` + return database.WithTx(ctx, nil, func(tx *sql.Tx) error { row := tx.QueryRowContext(ctx, query, b.ID) return row.Scan(&b.UpdatedOn) }) - return err } // TagsToString will convert linked tags to a comma separated string (used in forms) -- 2.47.2