From 6afc90166559390d8d3a9d04eecabe5464f48a7e Mon Sep 17 00:00:00 2001 From: Areas Date: Thu, 8 Mar 2018 18:42:55 +0800 Subject: [PATCH 01/10] simple version can save and restore data; communicate with cli --- app.py | 4 ++-- data.json | 1 + test.py | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 data.json create mode 100644 test.py diff --git a/app.py b/app.py index f4203a7..89d2015 100644 --- a/app.py +++ b/app.py @@ -13,7 +13,7 @@ def sync(): print "Request: ", json_data - return resp, 200 + return "ok", 200 if __name__ == "__main__": - app.run(debug=False) \ No newline at end of file + app.run(debug=False) diff --git a/data.json b/data.json new file mode 100644 index 0000000..42a61be --- /dev/null +++ b/data.json @@ -0,0 +1 @@ +[{"bookmark": 2, "actions": [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}, {"data": {"content": "\u5929\u7a7a\u4e4b\u57ce", "note_uuid": "9c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 0, "timestamp": 1518620066}, {"data": {"book_name": "idea"}, "type": "add_book", "id": 0, "timestamp": 1518620483}, {"data": {"content": "a game about life. To make life more chanllenging", "note_uuid": "1320ca22-9b3a-447a-bfad-4d160c373c4a", "book_name": "idea"}, "type": "add_note", "id": 0, "timestamp": 1518620483}]}] diff --git a/test.py b/test.py new file mode 100644 index 0000000..0e8ac3d --- /dev/null +++ b/test.py @@ -0,0 +1,40 @@ +from flask import Flask, request, jsonify +import zlib +import base64 +import json + +app = Flask(__name__) + +@app.route("/v1/sync", methods=["GET", "POST"]) +def sync(): + payload = json.loads(request.data) + raw_data = base64.b64decode(payload["actions"]) + json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) + + data = payload + data['actions'] = json_data + saveData(data) + print "Request: ", json_data + print payload + + return jsonify({u'bookmark':2,u'actions':[]}), 200 + +def saveData(data): + old = readData() + print old + old.append(data) + writeData(old) + + +def writeData(data): + with open("data.json", 'w') as outfile: + json.dump(data, outfile) + +def readData(): + with open("data.json") as infile: + data = json.load(infile) + return data + return [] + +if __name__ == "__main__": + app.run(debug=False) From 5dc39b4091717385f6c38b81887970985a69023c Mon Sep 17 00:00:00 2001 From: Areas Date: Thu, 8 Mar 2018 20:04:10 +0800 Subject: [PATCH 02/10] remove duplicate actions and save --- .gitignore | 2 ++ data.json | 2 +- test.py | 18 +++++++++++------- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 7bbc71c..2a96cc5 100644 --- a/.gitignore +++ b/.gitignore @@ -99,3 +99,5 @@ ENV/ # mypy .mypy_cache/ +/temp.py +data.json diff --git a/data.json b/data.json index 42a61be..7b0f5be 100644 --- a/data.json +++ b/data.json @@ -1 +1 @@ -[{"bookmark": 2, "actions": [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}, {"data": {"content": "\u5929\u7a7a\u4e4b\u57ce", "note_uuid": "9c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 0, "timestamp": 1518620066}, {"data": {"book_name": "idea"}, "type": "add_book", "id": 0, "timestamp": 1518620483}, {"data": {"content": "a game about life. To make life more chanllenging", "note_uuid": "1320ca22-9b3a-447a-bfad-4d160c373c4a", "book_name": "idea"}, "type": "add_note", "id": 0, "timestamp": 1518620483}]}] +[{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}, {"data": {"content": "\u5929\u7a7a\u4e4b\u57ce", "note_uuid": "9c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 0, "timestamp": 1518620066}, {"type": "add_book", "data": {"book_name": "music"}, "id": 0, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "\u5929\u7a7a\u4e4b\u57ce", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 0, "timestamp": 1518620066}, {"data": {"book_name": "idea"}, "type": "add_book", "id": 0, "timestamp": 1518620483}, {"data": {"content": "a game about life. To make life more chanllenging", "note_uuid": "1320ca22-9b3a-447a-bfad-4d160c373c4a", "book_name": "idea"}, "type": "add_note", "id": 0, "timestamp": 1518620483}, {"type": "add_note", "data": {"content": "a game about life. To make life more chanllenging", "note_uuid": "9320ca22-9b3a-447a-bfad-4d160c373c4a", "book_name": "idea"}, "id": 0, "timestamp": 1518620484}] \ No newline at end of file diff --git a/test.py b/test.py index 0e8ac3d..21403d3 100644 --- a/test.py +++ b/test.py @@ -11,19 +11,23 @@ def sync(): raw_data = base64.b64decode(payload["actions"]) json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) - data = payload - data['actions'] = json_data + data = json_data saveData(data) - print "Request: ", json_data - print payload return jsonify({u'bookmark':2,u'actions':[]}), 200 +def sillyDataAppend(old, data): + for item in data: + if (item not in old): + old.append(item) + + # maybe should compare *type* value + return sorted(old, key=lambda o:o['timestamp']) + def saveData(data): old = readData() - print old - old.append(data) - writeData(old) + newdata = sillyDataAppend(old, data) + writeData(newdata) def writeData(data): From 49241d92cee0d25e93b22e81444730676cd06f45 Mon Sep 17 00:00:00 2001 From: Areas Date: Fri, 9 Mar 2018 08:55:14 +0800 Subject: [PATCH 03/10] store actions and sort them by timestamp. But this method is false. --- test.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/test.py b/test.py index 21403d3..6791e4a 100644 --- a/test.py +++ b/test.py @@ -12,10 +12,26 @@ def sync(): json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) data = json_data - saveData(data) + # saveData(data) + mdata = [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}] + print fetchResponse(mdata) + return jsonify({u'bookmark':2,u'actions':[]}), 200 +def fetchResponse(data): + def fresh(x): + return x["timestamp"] > maxTimestamp + + maxTimestamp = getMaxTs(data) + print maxTimestamp + alldata = readData() + actions = filter(fresh, alldata) + return actions + +def getMaxTs(data): + return sorted(data, key=lambda o:o['timestamp'])[-1]["timestamp"] + def sillyDataAppend(old, data): for item in data: if (item not in old): From 885e9f90d76682ec7076a935695c40476d2fb65c Mon Sep 17 00:00:00 2001 From: Areas Date: Fri, 9 Mar 2018 20:17:30 +0800 Subject: [PATCH 04/10] a simple version server. save and extract actions by id. --- test.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/test.py b/test.py index 6791e4a..712d6b3 100644 --- a/test.py +++ b/test.py @@ -5,6 +5,9 @@ app = Flask(__name__) +## global server action id. should init in first run +id = 0 + @app.route("/v1/sync", methods=["GET", "POST"]) def sync(): payload = json.loads(request.data) @@ -13,12 +16,60 @@ def sync(): data = json_data # saveData(data) - mdata = [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}] - print fetchResponse(mdata) + # mdata = [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}] + # print fetchResponse(mdata) + # extract data to response to client + actions = fetchResponseById(payload["bookmark"]) + # save actions with generated id + saveActionsAndGenerateId(payload["bookmark"], data) + # constuct response + response = {} + # response["bookmark"] = lastId() # ? should I use u"bookmark" here? what is the difference? + response[u"bookmark"] = lastId() + response[u"actions"] = actions + + saveId() + + return jsonify(response), 200 + +## functions about id +def initId(): + global id + with open('./id') as infile: + id = json.load(infile)[u'id'] + +def saveId(): + with open('./id', 'w') as outfile: + json.dump({u'id':id}, outfile) + +def generateId(): + global id + id = id + 1 + return id + +def lastId(): + return id +def saveActionsAndGenerateId(bookmark, actions): + if bookmark == lastId(): + saveData(actions) + elif bookmark < lastId(): + saveData(actions) + else: + # maybe delete all client data and re-sync? + # but now do nothing. + print "bookmark is greater than last id in server" - return jsonify({u'bookmark':2,u'actions':[]}), 200 +def fetchResponseById(bookmark): + def fresh(x): + return x["id"] > bookmark + alldata = readData() + actions = filter(fresh, alldata) + return actions + + +## function about timestamp def fetchResponse(data): def fresh(x): return x["timestamp"] > maxTimestamp @@ -34,11 +85,17 @@ def getMaxTs(data): def sillyDataAppend(old, data): for item in data: - if (item not in old): + if (not isDuplicate(item, old)): + item["id"] = generateId() old.append(item) # maybe should compare *type* value - return sorted(old, key=lambda o:o['timestamp']) + return sorted(old, key=lambda o:o['id']) +def isDuplicate(item, collections): + for action in collections: + if (item["timestamp"] == action["timestamp"] and item["data"] == action["data"] and item["type"] == action["type"]): return True + return False + def saveData(data): old = readData() @@ -57,4 +114,5 @@ def readData(): return [] if __name__ == "__main__": + initId() app.run(debug=False) From 54d977819edd43ad5d410c4ca2876ba791f8a2d4 Mon Sep 17 00:00:00 2001 From: Areas Date: Fri, 9 Mar 2018 20:50:25 +0800 Subject: [PATCH 05/10] if data is None, set data as empty array. --- test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test.py b/test.py index 712d6b3..abbf1bd 100644 --- a/test.py +++ b/test.py @@ -15,6 +15,7 @@ def sync(): json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) data = json_data + if data is None: data = [] # saveData(data) # mdata = [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}] # print fetchResponse(mdata) From ec17d93aeb0129215e051c6e66b56a776f96a1ac Mon Sep 17 00:00:00 2001 From: Areas Date: Sat, 10 Mar 2018 07:57:10 +0800 Subject: [PATCH 06/10] version 1.0; function is complete, and unuseful lines are removed. --- test.py | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/test.py b/test.py index abbf1bd..5ec25af 100644 --- a/test.py +++ b/test.py @@ -14,15 +14,12 @@ def sync(): raw_data = base64.b64decode(payload["actions"]) json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) - data = json_data - if data is None: data = [] - # saveData(data) - # mdata = [{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}] - # print fetchResponse(mdata) + if json_data is None: data = [] # extract data to response to client actions = fetchResponseById(payload["bookmark"]) # save actions with generated id - saveActionsAndGenerateId(payload["bookmark"], data) + saveActionsAndGenerateId(payload["bookmark"], json_data) + # constuct response response = {} # response["bookmark"] = lastId() # ? should I use u"bookmark" here? what is the difference? @@ -69,21 +66,6 @@ def fresh(x): actions = filter(fresh, alldata) return actions - -## function about timestamp -def fetchResponse(data): - def fresh(x): - return x["timestamp"] > maxTimestamp - - maxTimestamp = getMaxTs(data) - print maxTimestamp - alldata = readData() - actions = filter(fresh, alldata) - return actions - -def getMaxTs(data): - return sorted(data, key=lambda o:o['timestamp'])[-1]["timestamp"] - def sillyDataAppend(old, data): for item in data: if (not isDuplicate(item, old)): @@ -92,6 +74,7 @@ def sillyDataAppend(old, data): # maybe should compare *type* value return sorted(old, key=lambda o:o['id']) + def isDuplicate(item, collections): for action in collections: if (item["timestamp"] == action["timestamp"] and item["data"] == action["data"] and item["type"] == action["type"]): return True From 09219980a3e69db1dbf1ebde74e4c0d2c1968965 Mon Sep 17 00:00:00 2001 From: Areas Date: Sat, 10 Mar 2018 08:00:14 +0800 Subject: [PATCH 07/10] modify .gitignore to ignore data.json and id file --- .gitignore | 3 ++- data.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2a96cc5..9eb16cb 100644 --- a/.gitignore +++ b/.gitignore @@ -100,4 +100,5 @@ ENV/ # mypy .mypy_cache/ /temp.py -data.json +*.json +id \ No newline at end of file diff --git a/data.json b/data.json index 7b0f5be..7ac5ed1 100644 --- a/data.json +++ b/data.json @@ -1 +1 @@ -[{"data": {"book_name": "test"}, "type": "add_book", "id": 0, "timestamp": 1518620066}, {"data": {"content": "\u5929\u7a7a\u4e4b\u57ce", "note_uuid": "9c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 0, "timestamp": 1518620066}, {"type": "add_book", "data": {"book_name": "music"}, "id": 0, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "\u5929\u7a7a\u4e4b\u57ce", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 0, "timestamp": 1518620066}, {"data": {"book_name": "idea"}, "type": "add_book", "id": 0, "timestamp": 1518620483}, {"data": {"content": "a game about life. To make life more chanllenging", "note_uuid": "1320ca22-9b3a-447a-bfad-4d160c373c4a", "book_name": "idea"}, "type": "add_note", "id": 0, "timestamp": 1518620483}, {"type": "add_note", "data": {"content": "a game about life. To make life more chanllenging", "note_uuid": "9320ca22-9b3a-447a-bfad-4d160c373c4a", "book_name": "idea"}, "id": 0, "timestamp": 1518620484}] \ No newline at end of file +[{"type": "add_book", "data": {"book_name": "music"}, "id": 1, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "music content 1", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 2, "timestamp": 1518620066}, {"data": {"book_name": "music"}, "type": "add_book", "id": 3, "timestamp": 1518620066}, {"data": {"content": "music content 1", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 4, "timestamp": 1518620066}, {"type": "add_book", "data": {"book_name": "music"}, "id": 5, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "music content 1", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 6, "timestamp": 1518620066}, {"data": {"book_name": "music"}, "type": "add_book", "id": 7, "timestamp": 1518620066}, {"data": {"content": "music content 3", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 8, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "music content 4", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 9, "timestamp": 1518620066}] \ No newline at end of file From 8f1749887cf02b4c00964af8d34ce08fbf1ac8c0 Mon Sep 17 00:00:00 2001 From: Areas Date: Sat, 10 Mar 2018 08:33:54 +0800 Subject: [PATCH 08/10] create data and if files if not exists. --- test.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/test.py b/test.py index 5ec25af..da0b921 100644 --- a/test.py +++ b/test.py @@ -2,12 +2,16 @@ import zlib import base64 import json +import os.path app = Flask(__name__) ## global server action id. should init in first run id = 0 +ID_FILE_PATH = "id" +DATA_FILE_PATH = "data.json" +## deal with cli data @app.route("/v1/sync", methods=["GET", "POST"]) def sync(): payload = json.loads(request.data) @@ -33,11 +37,11 @@ def sync(): ## functions about id def initId(): global id - with open('./id') as infile: + with open(ID_FILE_PATH) as infile: id = json.load(infile)[u'id'] def saveId(): - with open('./id', 'w') as outfile: + with open(ID_FILE_PATH, 'w') as outfile: json.dump({u'id':id}, outfile) def generateId(): @@ -81,6 +85,7 @@ def isDuplicate(item, collections): return False +## functions about read/write file def saveData(data): old = readData() newdata = sillyDataAppend(old, data) @@ -88,15 +93,25 @@ def saveData(data): def writeData(data): - with open("data.json", 'w') as outfile: + with open(DATA_FILE_PATH, 'w') as outfile: json.dump(data, outfile) def readData(): - with open("data.json") as infile: + with open(DATA_FILE_PATH) as infile: data = json.load(infile) return data return [] +## functions to initialize data files +def initDataFiles(): + if not os.path.isfile(ID_FILE_PATH): + id = 0 + saveId() + if not os.path.isfile(DATA_FILE_PATH): + writeData([]) + +## main function if __name__ == "__main__": + initDataFiles() initId() app.run(debug=False) From 21da470e3c64e1237b6156d13132a9a078237109 Mon Sep 17 00:00:00 2001 From: loot Date: Sat, 10 Mar 2018 09:15:51 +0800 Subject: [PATCH 09/10] Delete data.json this file should be auto-generated by server. --- data.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 data.json diff --git a/data.json b/data.json deleted file mode 100644 index 7ac5ed1..0000000 --- a/data.json +++ /dev/null @@ -1 +0,0 @@ -[{"type": "add_book", "data": {"book_name": "music"}, "id": 1, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "music content 1", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 2, "timestamp": 1518620066}, {"data": {"book_name": "music"}, "type": "add_book", "id": 3, "timestamp": 1518620066}, {"data": {"content": "music content 1", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 4, "timestamp": 1518620066}, {"type": "add_book", "data": {"book_name": "music"}, "id": 5, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "music content 1", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 6, "timestamp": 1518620066}, {"data": {"book_name": "music"}, "type": "add_book", "id": 7, "timestamp": 1518620066}, {"data": {"content": "music content 3", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "type": "add_note", "id": 8, "timestamp": 1518620066}, {"type": "add_note", "data": {"content": "music content 4", "note_uuid": "8c03a1d8-b313-401d-90d3-b1b873ed2de5", "book_name": "music"}, "id": 9, "timestamp": 1518620066}] \ No newline at end of file From 5da54cad7fa6e9ec368ec39bbdb77c5b7a75a419 Mon Sep 17 00:00:00 2001 From: Areas Date: Sat, 10 Mar 2018 09:23:05 +0800 Subject: [PATCH 10/10] mv test.py to app.py --- app.py | 104 +++++++++++++++++++++++++++++++++++++++++++++++-- test.py | 117 -------------------------------------------------------- 2 files changed, 101 insertions(+), 120 deletions(-) delete mode 100644 test.py diff --git a/app.py b/app.py index 89d2015..da0b921 100644 --- a/app.py +++ b/app.py @@ -1,19 +1,117 @@ -from flask import Flask, request +from flask import Flask, request, jsonify import zlib import base64 import json +import os.path app = Flask(__name__) +## global server action id. should init in first run +id = 0 +ID_FILE_PATH = "id" +DATA_FILE_PATH = "data.json" + +## deal with cli data @app.route("/v1/sync", methods=["GET", "POST"]) def sync(): payload = json.loads(request.data) raw_data = base64.b64decode(payload["actions"]) json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) - print "Request: ", json_data + if json_data is None: data = [] + # extract data to response to client + actions = fetchResponseById(payload["bookmark"]) + # save actions with generated id + saveActionsAndGenerateId(payload["bookmark"], json_data) + + # constuct response + response = {} + # response["bookmark"] = lastId() # ? should I use u"bookmark" here? what is the difference? + response[u"bookmark"] = lastId() + response[u"actions"] = actions + + saveId() + + return jsonify(response), 200 + +## functions about id +def initId(): + global id + with open(ID_FILE_PATH) as infile: + id = json.load(infile)[u'id'] + +def saveId(): + with open(ID_FILE_PATH, 'w') as outfile: + json.dump({u'id':id}, outfile) + +def generateId(): + global id + id = id + 1 + return id + +def lastId(): + return id + +def saveActionsAndGenerateId(bookmark, actions): + if bookmark == lastId(): + saveData(actions) + elif bookmark < lastId(): + saveData(actions) + else: + # maybe delete all client data and re-sync? + # but now do nothing. + print "bookmark is greater than last id in server" + +def fetchResponseById(bookmark): + def fresh(x): + return x["id"] > bookmark + + alldata = readData() + actions = filter(fresh, alldata) + return actions + +def sillyDataAppend(old, data): + for item in data: + if (not isDuplicate(item, old)): + item["id"] = generateId() + old.append(item) + + # maybe should compare *type* value + return sorted(old, key=lambda o:o['id']) + +def isDuplicate(item, collections): + for action in collections: + if (item["timestamp"] == action["timestamp"] and item["data"] == action["data"] and item["type"] == action["type"]): return True + return False + + +## functions about read/write file +def saveData(data): + old = readData() + newdata = sillyDataAppend(old, data) + writeData(newdata) + + +def writeData(data): + with open(DATA_FILE_PATH, 'w') as outfile: + json.dump(data, outfile) + +def readData(): + with open(DATA_FILE_PATH) as infile: + data = json.load(infile) + return data + return [] - return "ok", 200 +## functions to initialize data files +def initDataFiles(): + if not os.path.isfile(ID_FILE_PATH): + id = 0 + saveId() + if not os.path.isfile(DATA_FILE_PATH): + writeData([]) +## main function if __name__ == "__main__": + initDataFiles() + initId() app.run(debug=False) diff --git a/test.py b/test.py deleted file mode 100644 index da0b921..0000000 --- a/test.py +++ /dev/null @@ -1,117 +0,0 @@ -from flask import Flask, request, jsonify -import zlib -import base64 -import json -import os.path - -app = Flask(__name__) - -## global server action id. should init in first run -id = 0 -ID_FILE_PATH = "id" -DATA_FILE_PATH = "data.json" - -## deal with cli data -@app.route("/v1/sync", methods=["GET", "POST"]) -def sync(): - payload = json.loads(request.data) - raw_data = base64.b64decode(payload["actions"]) - json_data = json.loads(zlib.decompress(raw_data, 16 + zlib.MAX_WBITS)) - - if json_data is None: data = [] - # extract data to response to client - actions = fetchResponseById(payload["bookmark"]) - # save actions with generated id - saveActionsAndGenerateId(payload["bookmark"], json_data) - - # constuct response - response = {} - # response["bookmark"] = lastId() # ? should I use u"bookmark" here? what is the difference? - response[u"bookmark"] = lastId() - response[u"actions"] = actions - - saveId() - - return jsonify(response), 200 - -## functions about id -def initId(): - global id - with open(ID_FILE_PATH) as infile: - id = json.load(infile)[u'id'] - -def saveId(): - with open(ID_FILE_PATH, 'w') as outfile: - json.dump({u'id':id}, outfile) - -def generateId(): - global id - id = id + 1 - return id - -def lastId(): - return id - -def saveActionsAndGenerateId(bookmark, actions): - if bookmark == lastId(): - saveData(actions) - elif bookmark < lastId(): - saveData(actions) - else: - # maybe delete all client data and re-sync? - # but now do nothing. - print "bookmark is greater than last id in server" - -def fetchResponseById(bookmark): - def fresh(x): - return x["id"] > bookmark - - alldata = readData() - actions = filter(fresh, alldata) - return actions - -def sillyDataAppend(old, data): - for item in data: - if (not isDuplicate(item, old)): - item["id"] = generateId() - old.append(item) - - # maybe should compare *type* value - return sorted(old, key=lambda o:o['id']) - -def isDuplicate(item, collections): - for action in collections: - if (item["timestamp"] == action["timestamp"] and item["data"] == action["data"] and item["type"] == action["type"]): return True - return False - - -## functions about read/write file -def saveData(data): - old = readData() - newdata = sillyDataAppend(old, data) - writeData(newdata) - - -def writeData(data): - with open(DATA_FILE_PATH, 'w') as outfile: - json.dump(data, outfile) - -def readData(): - with open(DATA_FILE_PATH) as infile: - data = json.load(infile) - return data - return [] - -## functions to initialize data files -def initDataFiles(): - if not os.path.isfile(ID_FILE_PATH): - id = 0 - saveId() - if not os.path.isfile(DATA_FILE_PATH): - writeData([]) - -## main function -if __name__ == "__main__": - initDataFiles() - initId() - app.run(debug=False)