Simple list of applicants webapp - web-services

I am creating a web application that lists applicants and their position on a waiting list.
We need to be able to add new applicants to this list and remove applicants from the list. There will be under 10k applicants in the list.
Specifics:
I plan to write the app in Golang.
The list needs to be safe, I the program shuts down, it should be recoverable.
The app should contain this data for every applicant: Name, Student ID, position.
Questions:
How do I secure the list (lock?) so it is updated correctly for both if two updates to it is made at the same time?
Should I save the data in a database or use a file?
I need your help!
UPDATE:
Mockup code:
package main
import (
"log"
"sync"
"time"
"github.com/boltdb/bolt"
)
type applicant struct {
FirstName string
LastName string
StudentID string
Position int
}
type priorityList struct {
sync.Mutex
applicants []applicant
}
func (l *priorityList) newApplicant(fn string, ln string, sid string) error {
// add applicant to priorityList
return nil
}
func (l *priorityList) removeApplicant(sid string) error {
// remove applicant from priorityList
return nil
}
func (l *priorityList) editApplicant(sid string) error {
// edit applicant in priorityList
return nil
}
func main() {
// Database
db, err := bolt.Open("priorityList.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
log.Fatal(err)
}
defer db.Close()
}

If you use a file, you could use a Mutex to block concurrent writes.
Otherwise a database would be fine. For example BoltDB could be suitable. It is pure go and runs withing your program.

There are many approaches. You can use file and protect it with Go mutex or system lock. You can memory map the file for performance. You either can use BoltDB which is nice peace of software and provide needed machinery and can work in-process. If you write rare and mostly read, then constant DB https://github.com/colinmarc/cdb also looks interesting.
But, classic SQL DB has some advantages
You can use third party store for data and easely migrate when needed
You can access your data from third party app or just plain SQL
request
You can think about data schema and code logic separately

Related

How to fetch Coredata List in IntentHandler class (WidgetKit-SwiftUI)?

I am not able to fetch data in my IntentHandler class. My Goal is select Todo from the CoreData list and display it in Widget.
I am trying to display a list from CoreData in Widget Intent and I am expecting to resolve this issue.
extension IntentHandler : ConfigurationIntentHandling {
func provideTodoNameOptionsCollection(for intent: ConfigurationIntent, searchTerm: String?, with completion: #escaping (INObjectCollection<TodoData>?, Error?) -> Void) {
var arrTodoData = [TodoData]()
coreDH.getAllTodos().forEach { todos in
let todoIntent = TodoData(identifier: todos.id?.uuidString, display: todos.name ?? "")
arrTodoData.append(todoIntent)
}
let collection = INObjectCollection(items: arrTodoData)
completion(collection, nil)
}
}
class IntentHandler: INExtension{
let coreDH = CoreDataHandler.shared
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}
If your IntentHandler doesn't get called:
Ensure your Widget uses IntentConfiguration not StaticConfiguration
Ensure your time line provider conforms to IntentTimelineProvider
Run the app scheme, then run the intent scheme, you should be able to debug and breakpoints would work.
Widgets Code-along, part 3: Advancing timelines (5:31)
Add Configuration and Intelligence to Your Widgets
If you need to share data between your app and extension:
App's data is sandboxed and is not accessible by extension
Configure App Groups and you could create core data file in the shared container to be able to access in your extension
If App and Extension use exactly the same data you could use the same sqlite file in the shared container (both app and extension would have access to it)
If App and Extension use different data and there is only a small portion that is common, then use History Tracking
Configuring App Groups
Consuming Relevant Store Changes

Can I use a ForAll and UpdateIf within a local offline Powerapps collection?

Can anyone help?I need assistance to collect multiple records in a gallery and save it to a local collection when offline.
When my app is connected, my script uses a ForAll to go through all the gallery items then if the Question ID matches the ID in the gallery, it patches the records to the SQL database. This part works fine.
However, when offline, I collect the items and save them to a local collection called LocalAnswers. It only saves 1 record (instead of 20) and does not pull in the Question ID. I have tried inserting a ForAll and UpdateIf within my Collect function but can't seem to get it right. Any ideas?
If(
Connection.Connected,
ForAll(
Gallery2.AllItems,
UpdateIf(
AuditAnswers,
ID = Value(IDGal.Text),
{
AuditID: IDAuditVar,
Answer: Radio1.Selected.Value,
Action: ActionGal.Text,
AddToActionPlan: tglAction.Value
}
)
),
Collect(
LocalAnswers,
{
AuditID: IDAuditVar,
Answer: Radio1.Selected.Value,
Action: ActionGal.Text,
AddToActionPlan: tglAction.Value
}
)
);
Collect only pulls a single record because you only have a single record defined (everything between the {}).
I don't typically create collections from Gallery.AllItems but rather from a Data Source (Sharepoint, SQL, another Collection, etc.), so not sure if this will work without testing.
Try something like:
ForAll(Gallery2.AllItems,
Collect(colLocalAnswers,
{
AuditID: ThisRecord.AuditID, //or whatever the control's name is
Answer: ThisRecord.Radio1.Selected.Value,
Action: ThisRecord.ActionGal.Text,
AddToActionPlan: ThisRecord.tglAction.Value
}
)
);
SaveDate(colLocalAnswers, "localfile")

WSOS Identity - PIP Extension with a Set of Multiple Elements Returns Blank

Our testing demonstrated that the WSO2 PIP extension module implements a "Set" class connecting with the PDP integration (=AttributeFinder). This interface currently is only capable to transfer one single element.
Once we use a customized look-up for our groups definitions, generating a Set with multiple elements of type String, the WSO2 PDP returns a blank String with no information.
Sample Code from WSO2:
#Override
public Set<String> getAttributeValues(String subject, String resource, String action,
String environment, String attributeId, String issuer) throws Exception {
Set<String> roles = new HashSet<String>();
String role = findRole(subject);
if(role != null){
roles.add(role);
}
return roles;
}
PIP Extension Example Source for download:
https://svn.wso2.org/repos/wso2/carbon/platform/trunk/components/identity/org.wso2.carbon.identity.samples.entitlement.pip/src/main/java/org/wso2/carbon/identity/samples/entitlement/pip/
Our look-up program is using a String based data type, which matches the data type of the element, see XACML code below:
.
<AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="http://w3.red.com/subject/groupsUserBelong" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"></AttributeDesignator>
Access groups handling is a very common task in the XACML logic processing, so this is a crucial function for implementing XACML policies and rules.
Is this failure behaviour a bug (returns blank), or does WSO2 XACML deliver a programmatic implementation for a Set using multiple elements of Strings, automatically generating a string-bag according to the number of data elements, one String per element?
To complete the analysis, please check the sample code above, as well
as the matching abstract class named AbstractPIPAttributeFinder.
Both reference the return value named as "roles" and in the abstract class it is described as "values". Once the object to return is defined as a Set and the field names descries it in a plural, its basically self explaining the the values transported could be one or multiple elements that are part of the Set construction, usually each element of a String data-type.
The logic works well with a single element and it fails when using
multiple elements, which at the XACML interface returns a "blank" string in place of a "String-bag".
After detailed analysis of the PIP data flow through modules, we circled the issue inside the PIP extension program. Below you find the logic used to address and transfer the data fields. The new logic is able to transport multiple elements (for ex. groups, or roles) which was tested with an ObligationExpression as well as with a String-bag comparison, which both executed successfully after deploy of the new extension code.
public Set<String> getAttributeValues(String subject, String resource,
String action, String environment, String attributeId, String issuer)
throws Exception {
Set<String> myHash = new HashSet<String>();
Map<String, String> myMap = null;
if (attributeId.trim().equalsIgnoreCase("http://w3.red.com/subject/versionOfPIP")) {
myHash.add(myversion.toString().trim());
System.out.println(myversion.toString().trim());
} else if (attributeId.trim().equalsIgnoreCase("http://w3.red.com/subject/groupsUserBelong")) {
String myGroups = RedRedGroupAttrFinder.
getOnlyGroups(RedRedGroupAttrFinder.redGroupHTTPsSlaphAPI(subject));
ArrayList<String> myGroupsArrayL =RedRedGroupAttrFinder.convertStringToArraylist(myGroups);
for (String element : myGroupsArrayL) {
myHash.add(element.toString().trim());
}
} else if (attributeId.trim().equalsIgnoreCase("http://w3.red.com/subject/employeeCountryCode")) {
myMap = LdapHash.searchRedPagesByIntranetEmail(subject);
myHash.add(myMap.get(attributeId.substring(26).toString().trim()));
} else {
myHash.add("never");
}
return myHash;
}
}

Go Templates - Loading from an object store / Database

I'm rebuilding an app that supports customer specific templating (themes) from node.js to Go.
I'm currently using render to render my template files but what I actually need to do access templates that are stored in an object store such as Cloudfiles.
In node.js I've done this with express and I'm overriding the render() method but I've not been able to figure out how to do this in Go.
I essentially need to do something like this:
func (c *Controller) MyRouteHandler (rw http.ResponseWriter, req *http.Request) {
// retrieve the store from the context (assigned in middleware chain)
store := context.Get(req, "store").(*Store)
... do some stuff like load the entity from the database
// retrieve the template from the Object store and
// create the template instance (template.New("template").Parse(...))
tpl := c.ObjectStore.LoadTemplate(store, entity.TemplateFile)
// I know render's .HTML function takes the path to the template
// so I'll probably need to show the html a different way
c.HTML(rw, http.StatusOK, tpl, &PageContext{Title: "My Page", Entity: &entity})
}
I can dynamically include sub-templates by doing something like this if needed: http://play.golang.org/p/7BCPHdKRi2 but it doesn't seem like a great way if I'm honest.
I've searched for a solution to this but keep hitting road blocks. Any advice / assistance would be great.
Edit:
In essence, I'm asking the following:
How can I load a specific template from a datastore on a per-request basis.
How can I then send that as a response to the client
How can I load a specific template from a datastore on a per-request basis.
//take HTTP for example:
resp, err := http.Get("http://mytemplates.com/template1")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
templateString := string(body)
How can I then send that as a response to the client
tmpl, err := template.New("name").Parse(templateString)
tmpl.Execute(rw, &yourDataModel{})

Google App Engine Datastore - Testing Queries fails

I am currently trying to test a piece of my code that runs a query on the datastore before putting in a new entity to ensure that duplicates are not created. The code I wrote works fine in the context of the app, but the tests I wrote for that methods are failing. It seems that I cannot access data put into the datastore through queries in the context of the testing package.
One possibility might lie in the output from goapp test which reads: Applying all pending transactions and saving the datastore. This line prints out after both the get and put methods are called (I verified this with log statements).
I tried closing the context and creating a new one for the different operations, but unfortunately that didn't help either. Below is a simple test case that Puts in an object and then runs a query on it. Any help would be appreciated.
type Entity struct {
Value string
}
func TestEntityQuery(t *testing.T) {
c, err := aetest.NewContext(nil)
if err != nil {
t.Fatal(err)
}
defer c.Close()
key := datastore.NewIncompleteKey(c, "Entity", nil)
key, err = datastore.Put(c, key, &Entity{Value: "test"})
if err != nil {
t.Fatal(err)
}
q := datastore.NewQuery("Entity").Filter("Value =", "test")
var entities []Entity
keys, err := q.GetAll(c, &entities)
if err != nil {
t.Fatal(err)
}
if len(keys) == 0 {
t.Error("No keys found in query")
}
if len(entities) == 0 {
t.Error("No entities found in query")
}
}
There is nothing wrong with your test code. The issue lies in the Datastore itself. Most queries in the HR Datastore are not "immediately consistent" but eventually consistent. You can read more about this in the Datastore documentation.
So basically what happens is that you put an entity into the Datastore, and the SDK's Datastore "simulates" the latency that you can observe in production, so if you run a query right after that (which is not an ancestor query), the query result will not include the new entity you just saved.
If you put a few seconds sleep between the datastore.Put() and q.GetAll(), you will see the test passes. Try it. In my test it was enough to sleep just 100ms, and the test always passed. But when writing tests for such cases, use the StronglyConsistentDatastore: true option as can be seen in JonhGB's answer.
You would also see the test pass without sleep if you'd use Ancestor queries because they are strongly consistent.
The way to do this is to force the datastore to be strongly consistent by setting up the context like this:
c, err := aetest.NewContext(&aetest.Options{StronglyConsistentDatastore: true})
if err != nil {
t.Fatal(err)
}
Now the datastore won't need any sleep to work, which is faster, and better practice in general.
Update: This only works with the old aetest package which was imported via appengine/aetest. It does not work with the newer aetest package which is imported with google.golang.org/appengine/aetest. App Engine has changed from using an appengine.Context to using a context.Context, and consequently the way that the test package now works is quite different.
To compliment #JohnGB's answer in the latest version of aetest, there are more steps to get a context with strong consistency. First create an instance, then create a request from that instance, which you can use to produce a context.
inst, err := aetest.NewInstance(
&aetest.Options{StronglyConsistentDatastore: true})
if err != nil {
t.Fatal(err)
}
defer inst.Close()
req, err := inst.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)
}
ctx := appengine.NewContext(req)