Skip to content

Commit

Permalink
feat(back) : Handle quizzes updates
Browse files Browse the repository at this point in the history
Closes #15
  • Loading branch information
michaelcoll committed May 14, 2023
1 parent 2ca6421 commit 1fa79f0
Show file tree
Hide file tree
Showing 15 changed files with 368 additions and 27 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Nodes
node_modules

# build
# build / tests
quiz-app
internal/web/dist
/data
data.db
data.db-shm
data.db-wal

# ide
.idea/*
Expand Down
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The quiz wep app.`,

var version = "v0.0.0"

var Verbose bool
var verbose bool

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
Expand All @@ -46,5 +46,5 @@ func Execute() {
func init() {
rootCmd.Version = version

rootCmd.PersistentFlags().BoolVar(&Verbose, "verbose", false, "Verbose display")
rootCmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "Verbose display")
}
19 changes: 17 additions & 2 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import (
"context"
"fmt"
"os"
"os/signal"
"syscall"

"github.com/fatih/color"

"github.com/school-by-hiit/quiz-app/internal/back"
"github.com/school-by-hiit/quiz-app/internal/back/domain/banner"
Expand All @@ -37,9 +41,20 @@ Starts the server`,
banner.Print(version, banner.Serve)

module := back.New()
err := module.GetService().Sync(context.Background(), repoUrl, token)

// Handles the CTRL+C properly
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)

go func() {
<-c
module.GetService().Close()
os.Exit(0)
}()

err := module.GetService().Sync(context.Background(), repoUrl, token, verbose)
if err != nil {
fmt.Printf("Can't sync quizzes (%v)\n", err)
fmt.Printf("%s Can't sync quizzes (%v)\n", color.RedString("✗"), err)
os.Exit(-1)
}
module.GetPhotoController().Serve()
Expand Down
16 changes: 14 additions & 2 deletions db/queries/quiz.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
-- name: FindBySha1 :one
SELECT *
FROM quiz
WHERE sha1 = ?;

-- name: FindLatestVersionByFilename :one
SELECT max(version)
SELECT *
FROM quiz
WHERE filename = ?;
WHERE filename = ?
ORDER BY version DESC
LIMIT 1;

-- name: CreateOrReplaceQuiz :exec
REPLACE INTO quiz (sha1, name, filename, version)
Expand All @@ -23,3 +30,8 @@ VALUES (?, ?);
REPLACE INTO quiz_question_answer (question_sha1, answer_sha1)
VALUES (?, ?);

-- name: ActivateOnlyVersion :exec
UPDATE quiz
SET active = 0
WHERE filename = ?
AND version <> ?
4 changes: 2 additions & 2 deletions internal/back/domain/banner/banner.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ const (
⠘⢿⣿⣷⡀⠀⠀⠀⠀⠀⠀⢰⣌⠙⣇⢸⣿⣃⡄⠀⠀⠀⢤⣤⣴⣾⣿⡿⠟⠁
⠀⠀⠻⣿⣿⣷⣶⣶⡖⠀⠀⢸⣿⠀⣟⢸⡇⣿⣇⠀⠀⠀⠀⠈⠉⠁⠀⠀⠀⠀
⠀⠀⠀⠀⠉⠉⠉⠁⠀⠀⠀⠀⣿⢀⣿⢸⣷⢻⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⢸⡟⢸⣿⢸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀%s --- %s
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⢸⣇⢸⣿⠸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀===<< %s >>===
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⢸⡟⢸⣿⢸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀%s %s
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⢸⣇⢸⣿⠸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀=<< %s >>=
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⢸⣿⢠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⢸⣿⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀This is the way !
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠃⠸⠿
Expand Down
4 changes: 4 additions & 0 deletions internal/back/domain/model/quiz.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package model

import "time"

type Quiz struct {
Sha1 string `json:"id"`

Filename string `json:"filename"`
Name string `json:"name"`
Version int `json:"version"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Questions []QuizQuestion `json:"questions"`
}

Expand Down
22 changes: 22 additions & 0 deletions internal/back/domain/model/stats.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2023 Michaël COLL.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package model

type SyncStats struct {
Created int
Updated int
}
3 changes: 2 additions & 1 deletion internal/back/domain/repository/quizRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ type QuizRepository interface {
Connect()
Close()

FindBySha1(ctx context.Context, sha1 string) (model.Quiz, error)
FindLatestVersionByFilename(ctx context.Context, filename string) (model.Quiz, error)
FindAllActive(ctx context.Context) ([]model.Quiz, error)
Create(ctx context.Context, quiz model.Quiz) error
Update(ctx context.Context, quiz model.Quiz) error
Deactivate(ctx context.Context, sha1 string) error
ActivateOnlyVersion(ctx context.Context, filename string, version int) error
}
1 change: 1 addition & 0 deletions internal/back/domain/service/quizParseService.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func (s *QuizService) Parse(filename string, content string) (model.Quiz, error)
Sha1: getSha1(content),
Name: name,
Filename: filename,
Version: 1,
Questions: questions,
}, nil
}
Expand Down
5 changes: 2 additions & 3 deletions internal/back/domain/service/quizParseService_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package service

import (
"log"
"os"
"testing"

Expand All @@ -27,14 +26,14 @@ import (
func TestParse(t *testing.T) {
body, err := os.ReadFile("quiz.md")
if err != nil {
log.Fatalf("unable to test file: %v", err)
assert.Failf(t, "Fail to read quiz.md file", "%v", err)
}

s := New(nil)

actual, err := s.Parse("quiz.md", string(body))
if err != nil {
assert.Failf(t, "Fail to parse : %w", err.Error())
assert.Failf(t, "Fail to parse", "%v", err)
}

assert.Equal(t, "Version Control System", actual.Name)
Expand Down
80 changes: 73 additions & 7 deletions internal/back/domain/service/quizService.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package service
import (
"context"
"fmt"
"strconv"

"github.com/fatih/color"

Expand All @@ -34,31 +35,96 @@ func New(r repository.QuizRepository) QuizService {
return QuizService{r: r}
}

func (s *QuizService) Sync(ctx context.Context, repoUrl string, token string) error {
func (s *QuizService) Close() {
s.r.Close()
}

func (s *QuizService) Sync(ctx context.Context, repoUrl string, token string, verbose bool) error {

quizzes, err := s.ScanGitRepo(repoUrl, token)
if err != nil {
return err
}

var syncStats model.SyncStats
for _, quiz := range quizzes {
err := s.saveQuiz(ctx, quiz)
stats, err := s.saveQuiz(ctx, quiz, verbose)
if err != nil {
return err
}

syncStats = addStats(syncStats, stats)
}

fmt.Printf("%s Repo %s synced.\n", color.GreenString("✓"), color.BlueString(repoUrl))
if verbose {
if syncStats.Created > 0 || syncStats.Updated > 0 {
fmt.Printf("%s Repo synced (%s quiz(zes) created, %s quiz(zes) updated)\n",
color.GreenString("✓"),
color.BlueString(strconv.Itoa(syncStats.Created)),
color.BlueString(strconv.Itoa(syncStats.Updated)))
} else {
fmt.Printf("%s Repo synced %s\n",
color.GreenString("✓"),
color.BlueString(color.New(color.FgHiBlack).Sprintf(" — no changes")))
}
}

return nil
}

func (s *QuizService) saveQuiz(ctx context.Context, quiz model.Quiz) error {
func (s *QuizService) saveQuiz(ctx context.Context, quiz model.Quiz, verbose bool) (model.SyncStats, error) {

err := s.r.Create(ctx, quiz)
latestQuiz, err := s.r.FindLatestVersionByFilename(ctx, quiz.Filename)
if err != nil {
return err
if verbose {
fmt.Printf("%s Creating quiz %s\n",
color.GreenString("✓"),
quiz.Filename)
}

err = s.r.Create(ctx, quiz)
if err != nil {
return model.SyncStats{}, err
}

return model.SyncStats{
Updated: 0,
Created: 1,
}, nil
} else if latestQuiz.Sha1 != quiz.Sha1 {
quiz.Version = latestQuiz.Version + 1

if verbose {
fmt.Printf("%s Updating quiz %s to version %d\n",
color.GreenString("✓"),
quiz.Filename, quiz.Version)
}

err = s.r.Create(ctx, quiz)
if err != nil {
return model.SyncStats{}, err
}

err := s.r.ActivateOnlyVersion(ctx, quiz.Filename, quiz.Version)
if err != nil {
return model.SyncStats{}, err
}

return model.SyncStats{
Updated: 1,
Created: 0,
}, nil
} else {
return model.SyncStats{
Updated: 0,
Created: 0,
}, nil
}
}

return nil
func addStats(stat1 model.SyncStats, stat2 model.SyncStats) model.SyncStats {
return model.SyncStats{
Created: stat1.Created + stat2.Created,
Updated: stat1.Updated + stat2.Updated,
}
}
Loading

0 comments on commit 1fa79f0

Please sign in to comment.