uclaacm / teach-la-go-backend Goto Github PK
View Code? Open in Web Editor NEW๐ฑ Go Backend for Teach LA's Editor
Home Page: https://documenter.getpostman.com/view/10224331/TW6xmnn2
License: MIT License
๐ฑ Go Backend for Teach LA's Editor
Home Page: https://documenter.getpostman.com/view/10224331/TW6xmnn2
License: MIT License
Currently class.go
lacks a dedicated, comprehensive test code. We need test code to ensure functions like JoinClass
works properly. Similarly, alias_manager
only has a single test case - ideally there should be more, not only to test the functionality, but to test how much load it can withstand.
Right now, the DB#GetClass endpoint uses our word ID, which the frontend unfortunately has no access to. This should be a quick fix.
Following creation of a collaborative session as described in #30, an user must be able to join the session and work on the code together. This endpoint should match the route GET /collab/join/:sid
, where :sid
is the Session ID of the collaborative session.
Following initiation of a websocket connection, the client shall be considered to have joined.
This is a largely freeform issue. We would like to add more languages to the backend. For example, compiled languages. This is a moonshot goal, though.
Assigned to @lumisphere902.
To start a collaborative coding session, we're going to need to create an endpoint that will set up a session's websocket, and arbitrate the editor events between the two.
All this endpoint needs to do that's special is forward editor events from one client to the others, and handle save events for the program they are all working on.
For more reading, take a look at echo's documentation on websockets.
For some starter code, please review the collab
branch.
Whenever we create a program, we want to ensure that it is associated to a user profile. Currently, the CreateProgram function in handler/db.go does both operations separately. To do this, we should create a new function in db/db.go which both creates a program and associates it with a user. For inspiration, you can look at ForkProgram in db/program.go.
Right now, the extent of our backend's CLI is a single line that the user can run. Errors are reported to stdout, but past that, the backend executable is pretty slim. This isn't good for people who aren't looking to build the backend themselves or dig down into the code to understand how it works. It also doesn't make our lives phenomenal as it absconds verbosity changes, port number, networking behavior behind a complete rebuild process. To address this, we should create a proper CLI.
This issue will track the prep work for this.
The first issue is which library to use. Go has a ton of great CLI libraries out there, but I'd like to use urfave's cli. This one is a more feature-rich alternative to the stdlib. It is also under active development, which is always nice. Great guide on its manual page.
main
routine that calls the server. Make it into another function that takes relevant args that we extract from our CLI lib.The below information are future features
Next thing to tackle is which options to give the user. Here are a few that come to mind, and will spawn their own tickets in due time.
--no-cors, -n: Disable CORS middleware.
--creds, -c: Provide a path to the database credentials being used (defaults to `.env` and `*.json`, in that order).
--verbose, -v: Change the log level used by echo's logger middleware.
--port, -p: Change the port number.
--logfile, -l: Change the file logged to
At Will's behest we should have a DB#ClassGetPrograms endpoint available for the frontend's use.
See https://github.com/uclaacm/teach-la-go-backend/wiki/How-to-refactor-a-Backend-API, or #57 for an example.
See #57 as a reference
See https://github.com/uclaacm/teach-la-go-backend/wiki/How-to-refactor-a-Backend-API, or #57 for an example. A lot of the portion in the runTransaction
can be done much easier after #159 is done, so it can be left for last.
When a user creates a new program and then tries to delete it, the program is not removed from the page. Essentially, nothing visible happens on the page. However, on refreshing the page, the program is removed.
This would involve adding an API(s) to handler/class.go for submissions. This API would take in two PIDs (program IDs), a CID (class ID), and a UID (ID of the submitting user). For now, this API can call a mock function of the DB class which does nothing. The two PIDs correspond to the submission (student's program), and the assignment (teacher's program). The schema should match that of #97, but with the addition of the CID.
Your code should look similar to JoinClass up to line 192 or so, but with the correct inputs. The rest of the function can just be a comment or a dummy function call.
Before we actually add anything in terms of collaborative coding to the editor, we're going to want to add something a bit simpler. Let's start with Google Docs-style comments on programs.
For the backend, this should be pretty straightforward, just add a new property to our Program
struct that updates the comments on it.
The description of a comment is still a little freeform, but here's my intuition as to what it should have:
type Comment struct {
Author string `json:"author" firebase:"author"`
Start int `json:"start" firebase:"start"`
End int `json:"end" firebase:"end"`
}
Since we store program contents as a single string, we can just bind the comment to a range of characters in the sketch. The frontend will be in charge of updating the comments.
This new type would be nested within our Program
type:
type Program struct {
// ...
Comments []Comment `json:"comments" firebase:"comments"`
}
Use #57 as a reference.
I tried running the JoinClass (/class/join endpoint) and I think it's breaking because wid
is mixed up with cid
in the req struct. I think this also might be part of why Class tests are breaking
response: 404 Not Found: alias does not correspond to a class ID
See https://github.com/uclaacm/teach-la-go-backend/wiki/How-to-refactor-a-Backend-API, or #57 for an example.
These are simple CRUD functions, but any bad changes here could invalidate many other tests.
https://github.com/uclaacm/teach-la-go-backend/blob/master/db/mock.go
Use #57 as a reference.
See https://github.com/uclaacm/teach-la-go-backend/wiki/How-to-refactor-a-Backend-API, or #57 for an example.
Note that the CreateClass test would be commented out as a result of other refactors, and should be re-added with this issue's resolution
As a follow-up to the changes made in #32, we should futureproof and extend the interface with a way to create a session with a specific name, failing if the session already exists. This would be a good feature for teachers who want to keep their collaborative session IDs readable. For example:
POST .../collab/create
{
"name": "my session", // Optional field, defaults to random UUID.
"uid": "..."
}
Then, the response would be 201 Created
if the session was created with the name, and 400 Bad Request
if the request failed (and the session already existed).
It's no mystery that installing and configuring a Go development environment is a nontrivial task for new developers who are unfamiliar with the command line. One of the great parts of Go (or awful parts, if you aren't a fan of slightly larger binaries) is that all binaries are statically linked. I'm sure you can see where I'm going with this.
I'd like for us to release the backend in semver'd binaries. It means that frontend devs don't have to worry about setting up a working Go environment, installing our dependencies, building the project, and doing anything extra. Instead, they can just download a precompiled binary with our staging credentials.
Makefile
to build the backend for all relevant targets. The process of creating this should be pretty straightforward, and is a good way for new devs to familiarize themselves with the Go toolchain. Find a good resource on how to build for alternative targets here, and a good Go template Makefile
here.README
to reflect the new changes.This will be part of a larger focus on improving the backend's CLI and beginner-friendliness.
To allow student to submit their programs to the instructors, we need to store these submissions somewhere, such as an array within the class object. Each submission in the array should include:
{
submissionPID: string, // PID of the program being submitted
assignmentPID: string, // PID of the program/assignment this is being submitted to. Potentially optional
uid: string, // UID of the submitting user
}
Additionally, submissions should only be retrieved by the GetClass
function if the requesting user is an instructor, or was the one who submitted it (this can be done at a later time). One potential way of storing these submissions within the class object would be to add a subcollection (see this). Another way would be to use a simple array. This should be less scalable but have less overhead, which may be preferable for our use case
Overall, the important part of this ticket would be to create the struct within db/class.go and to modify the LoadClass and function in db/db.go to load the subcollection as well. Instead of modifying the existing functions for modifying the subcollection, you can add new functions which only interact with the submissions (e.g. AddClassSubmission, DeleteClassSubmission, etc.)
Teachers and students should be able to view their class' members. We can facilitate this through a new endpoint, POST /class/members
. The class CID should be passed in the request body, along with the UID of the user requesting it. We validate this UID is in the class, then provide the requester with the user IDs and display names of each member in said class. For example:
// POST /class/members
{
"cid": "SOME_CID",
"uid": "SOME_UID",
}
This will return:
{
"USER_ID0": {
"userField0": "...",
"userField1": "..."
},
"USER_ID1": {
...
}
}
See https://github.com/uclaacm/teach-la-go-backend/wiki/How-to-refactor-a-Backend-API, or #57 for an example.
Teachers should be able to request to view the latest version of their student's work, and receive live updates. To do this, they should send a message of the form:
{
"type": "READ",
"target": "some_uid"
}
This will cause the backend to enter a state of propagating packets from the given target
to the owner, and forwarding packets from the owner
to the given target
. For example, consider the following pseudocode:
out := read(someSocket)
if someSocket == owner {
// forward all packets from owner to target.
// receive packets from target, forward to owner.
}
This issue depends on #42, and may spawn another issue to abstract client connections on top of Go's websockets (for improved routing behavior).
This should just be a simple string field in https://github.com/uclaacm/teach-la-go-backend/blob/master/db/class.go
These are simple CRUD functions, but any bad changes here could invalidate many other tests.
https://github.com/uclaacm/teach-la-go-backend/blob/master/db/mock.go
Add breakpoint and step-through feature for Python editor
The helper functions RemoveUserFromClass
and RemoveUserFromClass
would also need to be moved. See #57 as a reference.
See #57 for an example. Note that the old API (the one that will be refactored) is named "CreateProgramTemp", and there already exists a CRUD function ("CreateProgram") in db.go
.
The assignment object should contain a reference to a program, as well as potential metadata. For the initial iteration, just a list of program IDs should be sufficient. I believe the most appropriate data structure would be a sub-collection of class documents, but an argument can also be made for a new root-level collection. In this case, a reference to a class would also be needed.
Assignment {
PID: string
submissions: string[]
}
If you take a look over at my work on krashanoff/db-context, you can see that we are refactoring our endpoints to be detached from our database operations. We do this by wrapping a connection to the database in a custom echo context (read more here) we pass to our handlers via custom middleware.
At present, the interface is fairly stable. We just need to concern ourselves with rewriting handlers to use the new context rather than making them member functions of the db#DB
type.
Right now, only the GetUser handler has been modified.
See https://github.com/uclaacm/teach-la-go-backend/wiki/How-to-refactor-a-Backend-API, or #57 for an example. This will also involve moving the loadClass
function to db/db.go
. You can find the function in https://github.com/uclaacm/teach-la-go-backend/blob/master/db/class.go#L230
For the User
struct, a new field should be added that checks whether the User is a developer account or not. This can be a simple bool
for the data type.
The code you would want to look at is here.
I suggest a change like this:
// User is a struct representation of a user document.
// It provides functions for converting the struct
// to firebase-digestible types.
type User struct {
Classes []string `firestore:"classes" json:"classes"`
DisplayName string `firestore:"displayName" json:"displayName"`
MostRecentProgram string `firestore:"mostRecentProgram" json:"mostRecentProgram"`
PhotoName string `firestore:"photoName" json:"photoName"`
Programs []string `firestore:"programs" json:"programs"`
UID string `json:"uid"`
DeveloperAcc bool `firestore:"developerAcc" json:"developerAcc"`
}
Each collaborative session should have an owner, who we will denote the teacher. This teacher will have an editor that is viewable by all members in the session (via sending a packet to the server). The teacher will also be able to edit their students' editors by sending packets.
However, prior to all of this, we must establish who is the owner of the session. I'm thinking we add the following to our session struct:
type Session struct {
// Map UIDs to their websocket.Conn
Conns map[string]*websocket.Conn
Teacher string
Lock sync.Mutex
}
The first person who joins a session can be made the owner, or the creation request can be modified to accommodate the new field. I leave this at the discretion of the implementer.
Following this, we can start forwarding packets between teacher and student, and roll from there.
To keep things consistent among user, program, and class endpoints, should the GetClass endpoint be a GET
request?
From server.go
:
Reverts #48. Now that tests are stable, we should be good to use the originally intended ID format
Use #57 as a reference.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.