Proper error handling when no entity is found - database

I'm writing a Go application which has a database package. Now in database package there are a couple of methods which you can call for getting an entity based on some fields.
I was wondering what is the best practice for error handling in Go when no entity is found. Should I return errors in my own database package or return nil as the value?
I know google's datastore returns error when no entity is found.
Right now I'm using gorm and it also returns error when no entity is found.
I'm wondering you can simply return nil as the value instead of returning an error. Am I missing a point?

If you are using gorm, there is a function specifically for that; namely,
// IsRecordNotFoundError returns true if error contains a RecordNotFound error
func IsRecordNotFoundError(err error) bool {}
You can use it as following:
err = db.Find(object).Error
if err != nil {
if gorm.IsRecordNotFoundError(err) {
// handle object not found
} else {
return err
}
}
and for your question:
I'm wondering you can simply return nil as the value instead of returning an error
It really depends on your design; so if you want to separate your database layer, then you should still inform the user about this error using your own exported error type and let them handle it as they wish.

you can use this code:
user:=&User{}
if db.First(&user, "username=?", mobile).RecordNotFound() {
return nil
}
return user

Related

How to raise ADF EO Validation Error from Groovy

I have an Entity validation of type script expression defined. Based on which validation logic (described in groovy) fails, I need to throw the respective error.
The groovy logic is as follows,
if( attr1.compareTo('a')){
adf.error.raise(argument1);
return false;
}
if( attr1.compareTo('b')){
adf.error.raise(argument2);
return false;
}
return true;
I have Added the messages under Failure Handling Tab as shown below
Screenshot
Now the problem is, I dont know what the argument should be?
I couldn't find any documentation online about this.
When Message Id (check screenshot) is provided as input, following error is obtained,
STRINGMANAGER: Key: not found in bundle oracle.javatools.resourcebundle.ResourceBundleRT

c.Infof undefined (type context.Context has no field or method Infof) google.golang.org/appengine/log error

In the Go Runtime i used the method c.Infof to log messages , but it fails to compile with the following error
c.Infof undefined (type context.Context has no field or method Infof) .
The Error clearly tells that the app engine context returned from c := appengine.NewContext(r) is of type context.Context and it doesnt have a method c.Infof on it. But contrary to this the documentation in https://godoc.org/google.golang.org/appengine/log suggests that this method exists . Another point to note , The method existed on the context returned by "appengine" (import "appengine" ) package , and this doesnt seem to exist on the context returned by the new package google.golang.org/appengine , what is c.Infof equivalent on the new Context of type context.Context returned by package "google.golang.org/appengine" ?
The example in the package documentation is not correct.
Use the log package functions to write to the App Engine log. Here's the corrected example:
c := appengine.NewContext(r)
query := &log.Query{
AppLogs: true,
Versions: []string{"1"},
}
for results := query.Run(c); ; {
record, err := results.Next()
if err == log.Done {
log.Infof(c, "Done processing results")
break
}
if err != nil {
log.Errorf(c, "Failed to retrieve next log: %v", err)
break
}
log.Infof(c, "Saw record %v", record)
}
The example in the package documentation was copied from the App Engine Classic package, but not updated to use the new functions. I suggest reporting this to the App Engine Team.

How to create a task for app engine task queue in Go?

Google's docs omit the most important aspect: How a Task is created. Can anybody complete the sample code:
import (
"appengine/datastore"
"appengine/taskqueue"
)
func f(c appengine.Context) {
err := datastore.RunInTransaction(c, func(c appengine.Context) error {
t := ... // WHY DOES GOOGLE NOT EXPLAIN THIS PART???
// Use the transaction's context when invoking taskqueue.Add.
_, err := taskqueue.Add(c, t, "")
// ...
})
// ...
}
I think what you need is described in the docs for datastore transactions.
So the missing code to create a task is:
t := &taskqueue.Task{Path: "/path/to/workertask"}
The reference for the Task type shows that Task is a struct with 10 or so fields, so you probably don't want to construct a Task yourself. However, it also provides the NewPOSTTask function (just below that):
NewPOSTTask creates a Task that will POST to a path with the given form data
I agree the documentation could be much better though.

Is memcache working in go on appengine?

I have an app that tries to store small images (less than 50kB) in memcache, but each call to memcache.Set() results in an error memcache: server error.
I'm on the shared memcache class, so I understand there is no service guarantee, but currently I have no service at all.
Is it a temporary outage? Am I just unlucky?
Here is the piece of code creating an item and calling memcache. ctx is the appengine context for the request. memkey is my key (a string). img_data is a string with my data.
This code works well in the local dev environment.
cache_item = &memcache.Item{
Key: memkey,
Value: bytes.NewBufferString(img_data).Bytes(),
}
err = memcache.Set(ctx, cache_item)
if err != nil {
ctx.Infof("Could not store image in memcache: %s", err)
}
If it's still happening, file a bug, but I suspect it was just a transient problem.
Incidentally, your Value initialiser is unnecessarily complex. This would work the same:
cache_item = &memcache.Item{
Key: memkey,
Value: []byte(img_data),
}

Getting weird error on datastore.Query.Run(c).Next(x)

I have not run into this particular error before, and when I Google it I can't find anything at all out there that even mentions it. I am using Go language, performing a standard datastore query like I have many times before using an iterator, and I get this error: "proto: required fields not set in datastore.QueryResult". See my code below, any ideas?
k, err := datastore.NewQuery("QBConnection").
Ancestor(datastore.NewKey(c, "Company", "", x.CompanyID, nil)).
Limit(1).
Run(c).
Next(x)
if err != nil {
if _, ok := err.(*datastore.ErrFieldMismatch); ok { err = nil } //ignore it if we can't load some fields
if err == datastore.Done { err = nil } //If we don't find it in datastore, then just return nil
if err != nil {return err}
}
I figure it out for my case, at least. I'm still unsure exactly what the error message is supposed to mean, and I got a different error when I ran this in the live environment (which led to my answer). On the live site it told me "ancestor missing id/name"... long story short, my x.CompanyID variable was not set properly before running the query. Not sure why the error messages were so different on dev/live, and sure would have helped to get the missing id/name error on my dev server... but oh well, problem solved.

Resources