ai cooking
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Orphan (#451)

* give recipes longer

* fix oprhaning and failred refereshes

* return early

---------

Co-authored-by: paul miller <paul.miller>

authored by

Paul Miller
paul miller
and committed by
GitHub
b47485d2 4929eb6c

+78 -22
+3
cmd/careme/web.go
··· 205 205 close(done) 206 206 }() 207 207 208 + // recipes can take several minutes to complete. 209 + ctx, cancel = context.WithTimeout(context.Background(), 3*time.Minute) 210 + defer cancel() 208 211 // Wait for all recipe generation goroutines to complete 209 212 slog.Info("Waiting for recipe generation goroutines to complete") 210 213
+35 -22
internal/recipes/server.go
··· 850 850 return 851 851 } 852 852 853 - if startTime, err := time.Parse(time.RFC3339Nano, startArg); err == nil { 854 - if time.Since(startTime) > time.Minute*10 { 855 - p, err := s.ParamsFromCache(ctx, hashParam) 856 - if err != nil { 857 - slog.ErrorContext(ctx, "failed to load params for hash", "hash", hashParam, "error", err) 858 - http.Error(w, "recipe not found or expired", http.StatusNotFound) 859 - return 860 - } 853 + startTime, err := time.Parse(time.RFC3339Nano, startArg) 854 + if err != nil { 855 + slog.ErrorContext(ctx, "failed to parse start time", "time", startArg, "error", err) 856 + redirectToHash(w, r, hashParam, true /*useStart*/) 857 + return 858 + } 859 + 860 + if time.Since(startTime) < time.Minute*10 { 861 + s.Spin(w, r) 862 + return 863 + } 864 + slog.WarnContext(ctx, "rekicking generation", "time", startArg, "hash", hashParam) 865 + 866 + p, err := s.ParamsFromCache(ctx, hashParam) 867 + if err != nil { 868 + slog.ErrorContext(ctx, "failed to load params for hash", "hash", hashParam, "error", err) 869 + http.Error(w, "recipe not found or expired", http.StatusNotFound) 870 + return 871 + } 861 872 862 - currentUser, err := s.storage.FromRequest(ctx, r, s.clerk) // just for logging purposes in kickgeneration. We could do this in the generateion function instead to avoid the extra call on every not found. 863 - if err != nil { 864 - if !errors.Is(err, auth.ErrNoSession) { 865 - slog.ErrorContext(ctx, "failed to get clerk user ID", "error", err) 866 - http.Error(w, "unable to load account", http.StatusInternalServerError) 867 - return 868 - } 869 - http.Redirect(w, r, "/", http.StatusSeeOther) 870 - return 871 - } 872 - s.kickgeneration(ctx, p, currentUser) 873 - redirectToHash(w, r, p.Hash(), true /*useStart*/) 873 + // this could fail becasuse clerk isn't refreshing? 874 + currentUser, err := s.storage.FromRequest(ctx, r, s.clerk) // just for logging purposes in kickgeneration. We could do this in the generateion function instead to avoid the extra call on every not found. 875 + if err != nil { 876 + if !errors.Is(err, auth.ErrNoSession) { 877 + slog.ErrorContext(ctx, "failed to get clerk user ID", "error", err) 878 + http.Error(w, "unable to load account", http.StatusInternalServerError) 874 879 return 875 880 } 881 + slog.WarnContext(ctx, "no valid session found from spin page.", "hash", hashParam) 882 + http.Redirect(w, r, "/", http.StatusSeeOther) 883 + return 876 884 } 877 - s.Spin(w, r) 885 + s.kickgeneration(ctx, p, currentUser) 886 + redirectToHash(w, r, p.Hash(), true /*useStart*/) 878 887 } 879 888 880 889 func (s *server) handleRecipes(w http.ResponseWriter, r *http.Request) { ··· 1021 1030 return r.Title, cooked[r.Hash].Cooked 1022 1031 }) 1023 1032 1024 - slog.InfoContext(ctx, "generating cached recipes", "params", p.String(), "hash", hash) 1033 + slog.InfoContext(ctx, "generating cached recipes", "params", p.String(), "hash", hash, "user_id", currentUser.ID) 1025 1034 shoppingList, err := s.generator.GenerateRecipes(ctx, p) 1026 1035 if err != nil { 1027 1036 slog.ErrorContext(ctx, "generate error", "error", err) ··· 1040 1049 func (s *server) Spin(w http.ResponseWriter, r *http.Request) { 1041 1050 w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate") 1042 1051 ctx := r.Context() 1052 + _, err := s.clerk.GetUserIDFromRequest(r) 1053 + signedIn := !errors.Is(err, auth.ErrNoSession) 1043 1054 spinnerData := struct { 1044 1055 ClarityScript template.HTML 1045 1056 GoogleTagScript template.HTML 1046 1057 Style seasons.Style 1058 + ServerSignedIn bool 1047 1059 RefreshInterval string // seconds 1048 1060 }{ 1049 1061 ClarityScript: templates.ClarityScript(ctx), 1050 1062 GoogleTagScript: templates.GoogleTagScript(), 1051 1063 Style: seasons.GetCurrentStyle(), 1064 + ServerSignedIn: signedIn, 1052 1065 RefreshInterval: "10", // seconds 1053 1066 } 1054 1067
+1
internal/templates/spinner.html
··· 25 25 </p> 26 26 </section> 27 27 </main> 28 + {{template "clerk_refresh.html" .}} 28 29 </body> 29 30 </html>
+39
internal/templates/templates_test.go
··· 3 3 import ( 4 4 "bytes" 5 5 "context" 6 + "html/template" 6 7 "strings" 7 8 "testing" 8 9 ··· 83 84 t.Fatalf("about page should render album comments from Go data, body: %s", rendered) 84 85 } 85 86 } 87 + 88 + func TestSpinTemplateIncludesClerkRefreshWhenEnabled(t *testing.T) { 89 + cfg := &config.Config{} 90 + cfg.Clerk.PublishableKey = "pk_test_123" 91 + if err := Init(cfg, "dummyhash.css"); err != nil { 92 + t.Fatalf("Init() error = %v", err) 93 + } 94 + t.Cleanup(func() { 95 + if err := Init(&config.Config{}, "dummyhash.css"); err != nil { 96 + t.Fatalf("cleanup Init() error = %v", err) 97 + } 98 + }) 99 + 100 + data := struct { 101 + ClarityScript template.HTML 102 + GoogleTagScript template.HTML 103 + Style seasons.Style 104 + ServerSignedIn bool 105 + RefreshInterval string 106 + }{ 107 + Style: seasons.GetCurrentStyle(), 108 + ServerSignedIn: false, 109 + RefreshInterval: "10", 110 + } 111 + 112 + var buf bytes.Buffer 113 + if err := Spin.Execute(&buf, data); err != nil { 114 + t.Fatalf("Spin.Execute() error = %v", err) 115 + } 116 + 117 + rendered := buf.String() 118 + if !strings.Contains(rendered, `data-clerk-publishable-key="pk_test_123"`) { 119 + t.Fatalf("spinner page should include Clerk bootstrap script, body: %s", rendered) 120 + } 121 + if !strings.Contains(rendered, `const serverSignedIn =`) || !strings.Contains(rendered, `!serverSignedIn && clerkSignedIn`) { 122 + t.Fatalf("spinner page should pass server sign-in state to Clerk refresh logic, body: %s", rendered) 123 + } 124 + }