-
Notifications
You must be signed in to change notification settings - Fork 1
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
Add in ability to edit pins #95
base: master
Are you sure you want to change the base?
Changes from 3 commits
ec3d1e8
d9fb5d5
811bea6
d7e69df
426c7bc
9129820
8b91a05
1bba243
29e1595
29df0f9
6f2166f
6aa4ffc
02e33cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,12 @@ | ||
import { SQLite } from 'expo'; | ||
import { SQLite, SecureStore } from 'expo'; | ||
import Sentry from 'sentry-expo'; | ||
import moment from 'moment'; | ||
import { pushRef } from './index'; | ||
import { convertArrayToLocations, convertToLocation, createLocationObject, saveCoordinates } from '../utils/database'; | ||
|
||
const DATABASE_VERSION_KEY = 'DATABASE_VERSION_KEY'; | ||
const DATABASE_VERSION = '2'; | ||
|
||
export function openDatabase(databaseName = 'locations.1.db') { | ||
return SQLite.openDatabase(databaseName); | ||
} | ||
|
@@ -23,30 +26,58 @@ export function executeTransaction(statement, args = null) { | |
}); | ||
} | ||
|
||
export function createDatabases() { | ||
function createDatabases() { | ||
return executeTransaction( | ||
'create table if not exists locations (id integer primary key not null, key text, coordinateKey text, createdAt text, resources text, status text, uploaded int)' | ||
'create table if not exists locations (id integer primary key not null, key text, coordinateKey text, createdAt text, resources text, status text, uploaded int, updated int)' | ||
); | ||
} | ||
|
||
export function clearDatabase() { | ||
return executeTransaction('drop table locations'); | ||
} | ||
|
||
export function deleteLocation(key) { | ||
return executeTransaction('delete from locations where key = ?', [key]); | ||
} | ||
|
||
export function updateUploadStatus(key, isUploaded) { | ||
return executeTransaction('update locations set uploaded = ? where key = ?', [isUploaded, key]); | ||
} | ||
|
||
export function updateLocalLocation(options) { | ||
const { resources, status, key } = options; | ||
// Uncomment this if user is ever able to change location position | ||
// SecureStore.setItemAsync(key, JSON.parse({ longitude, latitude })); | ||
export function replaceLocalLocationWithRemote(remoteLocation) { | ||
const { key, latitude, longitude, updated, status, resources } = remoteLocation; | ||
|
||
saveCoordinates(key, latitude, longitude); | ||
|
||
return executeTransaction('update locations set status = ?, resources = ?, updated = ?, uploaded = 1 where key = ?', [ | ||
status, | ||
JSON.stringify(resources), | ||
updated, | ||
key, | ||
]); | ||
} | ||
|
||
export async function updateLocalLocation(options, oldLocation) { | ||
const { key, updated = 0 } = oldLocation; | ||
const { latitude, longitude, resources, status } = options; | ||
|
||
saveCoordinates(key, latitude, longitude); | ||
|
||
const locationObject = createLocationObject(key, { | ||
...oldLocation, | ||
...options, | ||
uploaded: false, | ||
updated: oldLocation.uploaded ? oldLocation.updated + 1 : oldLocation.updated, | ||
}); | ||
|
||
return executeTransaction('update locations set resources = ?, status = ?, uploaded = 0 where key = ?', [ | ||
await executeTransaction('update locations set resources = ?, status = ?, uploaded = 0, updated = ? where key = ?', [ | ||
resources, | ||
status, | ||
updated + 1, | ||
key, | ||
]); | ||
|
||
return locationObject; | ||
} | ||
|
||
// fetches individual location | ||
|
@@ -80,9 +111,35 @@ export async function addLocalLocation(locationData) { | |
|
||
const createdAt = moment.utc(locationObject.created).toISOString(); | ||
await executeTransaction( | ||
'insert into locations (key, coordinateKey, createdAt, resources, status, uploaded) values (?, ?, ?, ?, ?, ?)', | ||
[key, key, createdAt, resourcesString, status, 0] | ||
'insert into locations (key, coordinateKey, createdAt, resources, status, uploaded, updated) values (?, ?, ?, ?, ?, ?, ?)', | ||
[key, key, createdAt, resourcesString, status, 0, 0] | ||
); | ||
|
||
return locationObject; | ||
} | ||
|
||
export async function createOrUpdateDatabase() { | ||
const version = await SecureStore.getItemAsync(DATABASE_VERSION_KEY); | ||
|
||
await createDatabases(); | ||
smaclell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (version === DATABASE_VERSION) { | ||
return Promise.resolve(); | ||
smaclell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
const locations = await fetchLocalLocations(); | ||
|
||
await clearDatabase(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels extremely dangerous. If something went wrong we would lose all the data ... I wonder if we could do something side by side. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose we could create a temporary database and store all the locations we pulled out of the old one and then delete it after we have populated the new one again. How would you feel about that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that would be fine. Simpler would be to have a different table to back things up into. You might be able to do it in a single query too. |
||
await createDatabases(); | ||
|
||
const transactions = locations.map((location) => { | ||
const { key, createdAt, resources, status, uploaded = 0, updated = 0 } = location; | ||
|
||
return executeTransaction( | ||
smaclell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'insert into locations (key, coordinateKey, createdAt, resources, status, uploaded, updated) values (?, ?, ?, ?, ?, ?, ?)', | ||
[key, key, createdAt, JSON.stringify(resources), status, uploaded, updated] | ||
); | ||
}); | ||
|
||
return Promise.all(transactions).then(() => SecureStore.setItemAsync(DATABASE_VERSION_KEY, DATABASE_VERSION)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this also need a transaction or to enforce that update is equal to update - 1 before it is being set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that's totally necessary. The value of
updated
will always be less than the new value. If it is less than the new value -1 then we are just making an even newer update to the local location and it should be a non-issue. Is there something else I am overlooking?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you might be okay with the local version, but you might not be able to guarantee that you are the only person to write to the remote data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I already do a check to ensure the remote data hasn't been updated more recently no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do, but there is still a race condition. Multiple people could try to update it at the same time which would still result in one overwriting the other if the concurrency bit is only set locally. I was expecting something to be passed up with the update to prevent races in firebase.
We can setup a remote rule for firebase to prevent updates if the version number is not expected.