Skip to content

Create Cron-Job for fetching contributions from gh archive dataset on bigquery #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: feat/contribution-service
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/joshsoftware/code-curiosity-2025/internal/app"
"github.com/joshsoftware/code-curiosity-2025/internal/app/cronJob"
"github.com/joshsoftware/code-curiosity-2025/internal/config"
)

Expand Down Expand Up @@ -43,6 +44,9 @@ func main() {

router := app.NewRouter(dependencies)

newCronSchedular := cronJob.NewCronSchedular()
newCronSchedular.InitCronJobs(dependencies.ContributionService)

server := http.Server{
Addr: fmt.Sprintf(":%s", cfg.HTTPServer.Port),
Handler: router,
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/ilyakaznacheev/cleanenv v1.5.0
github.com/jmoiron/sqlx v1.4.0
github.com/lib/pq v1.10.9
github.com/robfig/cron/v3 v3.0.1
golang.org/x/oauth2 v0.29.0
google.golang.org/api v0.231.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgm
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=
Expand Down
15 changes: 0 additions & 15 deletions internal/app/contribution/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ type handler struct {
}

type Handler interface {
FetchUserLatestContributions(w http.ResponseWriter, r *http.Request)
FetchUsersAllContributions(w http.ResponseWriter, r *http.Request)
}

Expand All @@ -23,20 +22,6 @@ func NewHandler(contributionService Service) Handler {
}
}

func (h *handler) FetchUserLatestContributions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

err := h.contributionService.ProcessFetchedContributions(ctx)
if err != nil {
slog.Error("error fetching latest contributions")
status, errorMessage := apperrors.MapError(err)
response.WriteJson(w, status, errorMessage, nil)
return
}

response.WriteJson(w, http.StatusOK, "contribution fetched successfully", nil)
}

func (h *handler) FetchUsersAllContributions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

Expand Down
24 changes: 24 additions & 0 deletions internal/app/cronJob/cronjob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cronJob

import (
"context"
"log/slog"
"time"
)

type Job interface {
Schedule(c *CronSchedular) error
}

type CronJob struct {
Name string
}

func (c *CronJob) Execute(ctx context.Context, fn func(context.Context)) {
slog.Info("cron job started at", "time ", time.Now())
defer func() {
slog.Info("cron job completed")
}()

fn(ctx)
}
32 changes: 32 additions & 0 deletions internal/app/cronJob/dailyJob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cronJob

import (
"context"

"github.com/joshsoftware/code-curiosity-2025/internal/app/contribution"
)

type DailyJob struct {
CronJob
contributionService contribution.Service
}

func NewDailyJob(contributionService contribution.Service) *DailyJob {
return &DailyJob{
contributionService: contributionService,
CronJob: CronJob{Name: "Fetch Contributions Daily"},
}
}

func (d *DailyJob) Schedule(s *CronSchedular) error {
_, err := s.cron.AddFunc("0 1 * * *", func() { d.Execute(context.Background(), d.run) })
if err != nil {
return err
}

return nil
}

func (d *DailyJob) run(ctx context.Context) {
d.contributionService.ProcessFetchedContributions(ctx)
}
38 changes: 38 additions & 0 deletions internal/app/cronJob/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cronJob

import (
"log/slog"
"time"

"github.com/joshsoftware/code-curiosity-2025/internal/app/contribution"
"github.com/robfig/cron/v3"
)

type CronSchedular struct {
cron *cron.Cron
}

func NewCronSchedular() *CronSchedular {
location, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
slog.Error("failed to load IST timezone", "error", err)
}

return &CronSchedular{
cron: cron.New(cron.WithLocation(location)),
}
}

func (c *CronSchedular) InitCronJobs(contributionService contribution.Service) {
jobs := []Job{
NewDailyJob(contributionService),
}

for _, job := range jobs {
if err := job.Schedule(c); err != nil {
slog.Error("failed to execute cron job")
}
}

c.cron.Start()
}
6 changes: 2 additions & 4 deletions internal/app/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import (
)

type Dependencies struct {
AuthService auth.Service
UserService user.Service
ContributionService contribution.Service
AuthHandler auth.Handler
UserHandler user.Handler
ContributionHandler contribution.Handler
Expand All @@ -40,8 +39,7 @@ func InitDependencies(db *sqlx.DB, appCfg config.AppConfig, client config.Bigque
contributionHandler := contribution.NewHandler(contributionService)

return Dependencies{
AuthService: authService,
UserService: userService,
ContributionService: contributionService,
AuthHandler: authHandler,
UserHandler: userHandler,
ContributionHandler: contributionHandler,
Expand Down
1 change: 0 additions & 1 deletion internal/app/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ func NewRouter(deps Dependencies) http.Handler {

router.HandleFunc("PATCH /api/v1/user/email", middleware.Authentication(deps.UserHandler.UpdateUserEmail, deps.AppCfg))

router.HandleFunc("GET /api/v1/user/contributions/latest", middleware.Authentication(deps.ContributionHandler.FetchUserLatestContributions, deps.AppCfg))
router.HandleFunc("GET /api/v1/user/contributions/all", middleware.Authentication(deps.ContributionHandler.FetchUsersAllContributions, deps.AppCfg))
return middleware.CorsMiddleware(router, deps.AppCfg)
}