Skip to content
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

[WIP] Resolver and Serialisation #21

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

iDevelopThings
Copy link

@iDevelopThings iDevelopThings commented Sep 25, 2022

The idea/solution i mentioned in #20

  • Implemented RPCRawResponse/Serialisation changes
  • Implemented the query resolver solution
  • Started tests for resolver/serialisation

Only handled the regular Query() function so far
It's pretty hacky in some places, was a quick put together as POC

TODO: Need to clean up the panics and find better solutions to them

Keitio and others added 5 commits September 23, 2022 20:25
…e and provides ability to define scope, ns, db etc
This will allow us to do individual tests without re-creating db each time

Wrote tests for `SignupUser` & `SigninUser`
- Implemented RPCRawResponse/Serialisation changes
- Implemented the query resolver solution
- Started tests for resolver/serialisation

TODO: Need to clean up the panics and find better solutions to them
env_util.go Outdated Show resolved Hide resolved
err.go Outdated
func (self PermissionError) Error() string {
return fmt.Sprint("Unable to access record:", self.what)
func (pe PermissionError) Error() string {
return fmt.Sprint("Unable to access record:", pe.what)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of Sprint, you can just return "Unable to access record: " + pe.what

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Github Copilot 😅 will change


// Query creates a new query resolver
// It would be ideal if we create a global for *DB
func Query[T any](db *DB, ctx context.Context, query string, params ...any) *QueryResolver[T] {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The context should always be the first parameter here
And creating a global db would be kind of nice to use, but horrendous to test and using multiple db connections would be near impossible

func Query[T any](db *DB, ctx context.Context, query string, params ...any) *QueryResolver[T] {
var paramsData = QueryParams{}
if len(params) > 0 {
paramsData = params[0].(QueryParams)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is extremely unsafe to do, just take a params ...QueryParams instead, and document that only the first one is used

Time string `json:"time"`
}

type QueryParams = map[string]any
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should only be called Map ? It would be easier to use

return resolver.resolve(db)
}

func (r *QueryResolver[T]) resolve(db *DB) *QueryResolver[T] {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first line of this method should probably be something along the lines of

if r.err != nil {
    return r
}

so we don't work on an invalid object

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This r.err is the error we found during processing of the RPC Response, not a local error with the QueryResolver ^^

rpc.go Outdated

decodedError bool
hasError bool
error *RPCError
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those 3 members look strange to me, hasError should be error != nil IMO
and document what decodedError is

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are mainly just states so we know that we've processed looking for the error in the raw bytes,
decodedError = did we try to decode it?
hasError = we decoded it & we found an error

rpc.go Outdated
return nil
}

func (res *RPCRawResponse) HasError() bool {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wayyy too complicated for a Go error check
The way to check errors in go is if err != nil, so this work should be done before the user gets the result back

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, it needs some refactoring

My Idea was that we run the check once, and then we rely on the error/hasError states from the above suggestion

type TokenData struct {
IssuedAt int `json:"iat"`
NotBefore int `json:"nbf"`
ExpiresAt int `json:"exp"`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those should be time.Time (this implies a bit more work on the driver side)

"testing"

"github.com/surrealdb/surrealdb.go"
"github.com/test-go/testify/suite"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we could not use testify that would be great, Go has a fantastic standard library that does most of the work for us, and testify is a huge dependency (go has no concept of dev dependencies, so the entire testify and its many dependencies are pulled if you want to use this driver)

@iDevelopThings
Copy link
Author

Sorry for any spam 😅

I will see if i can work through these changes tomorrow and clear some bits up + add the go build tags for 18+

@iDevelopThings
Copy link
Author

@Keitio what would we do with this panic here?

We wouldn't want to cancel the context/close the ws right? 🤔

CleanShot 2022-09-26 at 14 46 47

@Keitio
Copy link

Keitio commented Sep 26, 2022

Yeah, logging the error and then a continue would be more appropriate

- Complete refactor of a lot of the logic and some further abstractions
- Added handling for the regular crud methods, create, update, modify etc
- Commented a lot of the code I wrote

Issues:
- Currently there's a problem where the normal db.create, update etc, fail because the db send method returns RPCRawResponse, not sure how to handle that situation at the moment
@iDevelopThings iDevelopThings marked this pull request as ready for review September 26, 2022 17:29
@iDevelopThings
Copy link
Author

F, I thought ready for review, would request another one, my bad...

Copy link

@Keitio Keitio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My opinion is that i find the API too large to be searchable, and that's for a simple CRUD (mostly) driver
I personally think we should strive for the simplest API that's useful because it will be better understood (thus less isssues)
I think this is mostly due to exposing internal implementation details way too much (IMO even the WS should be hidden to end users)
This also doesn't strike me as very "go-like", but that's probably a me issue

"context"
)

type QueryResolver[T any] struct {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this type be exported ?


var (
// ErrResolvedQueryResultIsInvalid Need a better name :|
ErrResolvedQueryResultIsInvalid = errors.New("the result from the database response is not valid, expected an array")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ErrInvalidRpcResult ? make it so that it covers more cases than just array expected, but just a general rpc result problem

@iDevelopThings
Copy link
Author

Yeah I agree, it's quite large, but it's more of an optional/additional layer the dev can opt into to keep things a bit more simplified, for example, using .Query() and getting your individual item out of the result each time, gets boring fast, and then you write a wrapper to do it.... then every person does the same thing, it makes sense to have an option for that being handled

Things that you think shouldn't be exposed like that, can be sorted, it's just a WIP, on my personal code, i don't usually care too much about things not being exported 😅

@Keitio
Copy link

Keitio commented Sep 26, 2022

Yep, no problems with that ! Was just stating my personal opinion on the current state of your branch just for you to get some (albeit very opinionated) feedback

@tobiemh tobiemh marked this pull request as draft September 27, 2022 23:38
@phughk phughk added the stale label May 23, 2023
@phughk
Copy link
Contributor

phughk commented May 23, 2023

Hey @iDevelopThings 👋 Thanks for opening this! Do you want to continue trying to merge this or can we close this PR? Will assign @timpratim if we do decide to continue. It would be good to resolve the merge conflicts to make it easier to review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants