-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add code_structure & database_design doc
Signed-off-by: Arnob kumar saha <arnob@appscode.com>
- Loading branch information
1 parent
50b155d
commit 01764b5
Showing
3 changed files
with
215 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,14 @@ | ||
# praromvik | ||
# praromvik | ||
|
||
The staring point, that will define your path on the DevOps journey ! | ||
|
||
## Contribution guidelines | ||
|
||
Want to help improve praromvik? Please read the design docs [here](https://github.com/Praromvik/praromvik/tree/master/docs). | ||
|
||
## Support | ||
|
||
To speak with us, please leave a message on our email `praromvik.hq@gmail.com`. | ||
To receive product announcements, follow us on [Twitter](https://twitter.com/PraromvikHq), [LinkedIn](https://www.linkedin.com/company/praromvik/), [Facebook](https://www.facebook.com/profile.php?id=61557462003505). | ||
|
||
If you have found a bug with Praromvik or want to request for new features, please [file an issue](https://github.com/praromvik/praromvik/issues/new). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
Description on each of the packages | ||
|
||
# cmd | ||
Under the root command, there is only one subcommand named start_server. We use the routers package from it & start the server. | ||
|
||
# routes | ||
We have these types of routes: | ||
|
||
`user_auth`: signUp, signIn, signOut | ||
|
||
`course`: | ||
i) get/list -> general authenticated users can do it. | ||
ii) create/update -> admin or moderators can do. | ||
iii) delete -> only admin can do it. | ||
|
||
For get,update & delete calls(those work on a specific course uid), we utilize a context middleware for injecting context data. | ||
|
||
There is one special route for providing role to a user. It requires the admin access. | ||
|
||
# pkg | ||
-`pkg.auth`: | ||
|
||
We store these fields in the redis session: | ||
i) authenticated, ii) role, iii) userName, iv) userIP, v) user_agent | ||
There are some getters implemented in the session.go file. | ||
|
||
|
||
|
||
-`pkg.error` | ||
|
||
-`pkg.middleware`: | ||
|
||
There are 4 types of middlewares in this package. | ||
i) global middleware: For example logger, urlFormatter etc. | ||
|
||
ii) common security middleware: To check if a session is valid & authenticated. | ||
|
||
iii) access related middleware: To check if the role(in session) is matched. | ||
|
||
iv) context middleware: To append additional info to the context. | ||
|
||
|
||
# handlers | ||
`routes -> handlers -> models` | ||
|
||
Routes package will call functions from handlers package. And handlers package will call functions from models package. | ||
We should be strict to this design principle to avoid implementation complexity & circular dependencies. | ||
|
||
In general, the handlers are pretty straight-forward. They contain functions like Create, Get, List, Update, Delete etc. | ||
|
||
# models | ||
This is the actual working unit. The API & common constants are declared here. Also, it is responsible for all the database calls. | ||
|
||
|
||
1) `models.db.client`: | ||
A special package only to initialize the db clients thorough init(). | ||
|
||
2) `models.db`: | ||
DB calls are implemented here. No one calls the DB directly except this package. | ||
|
||
3) `models.course`: | ||
Dedicated package for course related methods. Intended to only be called from `handlers/course`. | ||
|
||
4) `models.user`: | ||
Dedicated package for user related methods. Intended to only be called from `handlers/user`. | ||
|
||
|
||
--- | ||
There are some other non-code packages/files worth mentioning. | ||
|
||
`docs`: Holds the documentation files. | ||
|
||
`hack`: Holds the utility script files. | ||
|
||
`.env` file: Export the required ENVs to run this backend server. | ||
|
||
`req.http` file: Holds the curl request-response examples for the implemented http routes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
## API | ||
``` | ||
type Course struct { | ||
CourseId string `json:"_id" bson:"_id"` | ||
Title string `json:"title" bson:"title"` | ||
Description string `json:"description" bson:"description"` | ||
Instructors []string `json:"instructors" bson:"instructors"` | ||
Moderators []string `json:"moderators" bson:"moderators"` | ||
StartDate date.Date `json:"startDate" bson:"startDate"` | ||
EndDate date.Date `json:"endDate" bson:"endDate"` | ||
Duration int `json:"duration" bson:"duration"` // Duration in week | ||
Capacity int `json:"capacity" bson:"capacity"` | ||
Students []string `json:"students" bson:"students"` | ||
Price int `json:"price" bson:"price"` | ||
Image []byte `json:"image" bson:"-"` | ||
} | ||
``` | ||
|
||
``` | ||
type Lesson struct { | ||
LessonID string `json:"_id" bson:"_id"` | ||
Title string `json:"title" bson:"title"` | ||
Contents []ContentRef `json:"contents" bson:"contents"` | ||
} | ||
type ContentRef struct { | ||
ID string `json:"id" bson:"id"` | ||
Title string `json:"title" bson:"title"` | ||
} | ||
type Content struct { | ||
ContentID string `json:"_id" bson:"_id"` | ||
Title string `json:"title" bson:"title"` | ||
Type string `json:"type" bson:"type"` // video, resource, quiz, lab | ||
Data []byte `json:"data" bson:"data"` | ||
LessonRef UUID `json:"lessonRef" bson:"lessonRef"` | ||
} | ||
``` | ||
|
||
|
||
## A concrete Example | ||
``` | ||
Course name: Mastering golang | ||
<Lessons>: | ||
Introduction: | ||
Why Go? | ||
Installation | ||
<resources> | ||
<quiz> | ||
Concurrency in Go: | ||
channels | ||
mutex | ||
<lab1> | ||
<resources> | ||
go routines | ||
<lab2> | ||
Conclusion | ||
thank you | ||
``` | ||
|
||
For the `lab1` under 'Concurrency in Go', url will be like: | ||
http://praromvik.com/course/mastering_golang/concurrency_lab_1/ | ||
Intentionally cutting off the lesson id part to keep the url shorter. | ||
|
||
--- | ||
|
||
We have divided a single course into 2 different databases. One for holding the metadata, & one for holding the actual information. | ||
Again the actual information is divided into two collections. One will be called once, & the other one will be called several times (with specific contentID) from the frontend. | ||
### `praromvik.courses` collection | ||
This will hold the metadata information only. | ||
``` | ||
{ | ||
"_id": "mastering_golang", | ||
"title": "Mastering Golang", | ||
"instructors": []string{<some_user_ids>}, | ||
"students": []string{<some_user_ids>} | ||
} | ||
``` | ||
Removed the lessons slice above to avoid multiple reference update on create/delete calls. | ||
|
||
### `mastering_golang.lessons` collection | ||
The _id format is `<4_digit_serial_number>_<epoch_time>` | ||
``` | ||
{ | ||
"_id": "<0001_1715524983>", | ||
"title": "Introduction", | ||
"contents": []string{<_ids>} | ||
}, | ||
{ | ||
"_id": "<0002_1715527643>", | ||
"title": "Concurrency in Go", | ||
"contents": []string{"channel", "concurrency_lab_1", "resouce_from_doc"} | ||
} | ||
``` | ||
|
||
### `mastering_golang.contents` collection | ||
``` | ||
{ | ||
"_id": "channel", | ||
"title": "Channel", | ||
"type": "Video", | ||
"lessonRef": "0002_1715527643" | ||
}, | ||
{ | ||
"_id": "concurrency_lab_1", | ||
"title": "Hands-on the Go channel", | ||
"type": "Lab", | ||
"lessonRef": "0002_1715527643" | ||
}, | ||
{ | ||
"_id": "resouce_from_doc", | ||
"title": "Additional learing resouces", | ||
"type": "Written", | ||
"lessonRef": "0002_1715527643" | ||
}, | ||
``` | ||
|
||
So the `RESTRICTIONS` are: | ||
|
||
i) course ids have to be unique. | ||
|
||
ii) content ids within a course have to be unique. | ||
|
||
iii) both course & content ids have to be <= 24 characters, as they will be used as _id in mongodb. |