首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >通过加/减更新放大数据存储项的价值?

通过加/减更新放大数据存储项的价值?
EN

Stack Overflow用户
提问于 2021-12-16 19:50:06
回答 1查看 176关注 0票数 0

我希望使用数据存储来根据存储在数据库中的当前值更新一个值。在文档中,它显示了一个零售计数器用例。但是你应该如何实现这种设置呢?

一个小例子:

我有一张存货表,里面有一件物品和一件物品的柜台:

代码语言:javascript
运行
复制
type Inventory @model {
id: ID!
name: String!
count: Int!}

如果我想保存一个新的Inventory,我可以这样做:

代码语言:javascript
运行
复制
Inventory inventory = Inventory(id,'product1',10);
Amplify.Datastore.save(inventory);

然后,我知道要更新,我可以使用相同的ID的Amplify.Datastore.save(inventoryUpdatedModel),而放大器将更新存储中的项目。到目前一切尚好。

那么,如果多个设备更改了与示例中相同的值,该怎么办?

开始:计数= 10;

1:设备1 ->将5添加到计数(10 +5= 15)

2:设备2 ->从计数中减去3(10-3= 7)

3:两种设备都更新数据存储和读取值。

目前,只显示最新的值(示例中为7),其中所需的答案为12。(10+5-3 = 12)

到目前为止,我已经尝试过:

  1. 在数据库保存之前查询它,但是当多个设备同时执行操作时,会出现明显的并发问题。
  2. 添加一个名为updateInventoryCount(inventoryID,numberToAdd)的新表,然后一次只在一个设备上处理该表中的数据。平衡对同一个ID的任何更新的值,然后删除它们实际上是有效的,但它根本不是一个完美的解决方案。

我想要的是类似于这样的东西:Amplify.Datastore.updateValue(ID,-3);扩增->采用旧值,减去3,用相同的命令更新appsync

EN

回答 1

Stack Overflow用户

发布于 2021-12-29 11:16:46

我选择的方向是这样的,如果我离目标很远,请随时告诉我!

基本上:运行一个服务来检测与AWS同步的补充表中的更改,并且只允许该服务在本地更改数据,而不是允许AWS更改本地受保护的表。

的优点:

  • 根本不依赖任何服务器代码。
  • 断断续续的网络很好,更新在多个设备上保持不变,
  • 只使用颤振放大api

缺点:

  • 将创建更多对AWS的写入。
  • 卷曲

Make models:无法让模型通过代码代码直接获取相关对象(尽管看起来管道就是要这样做的)因此,我使用“表行”ID并执行两个Amplify.DataStore.query(model.classType)操作来获取本地节点的inventory,然后是泛型ticketitem数据

代码语言:javascript
运行
复制
type Inventory @model {
  id:ID!
  clientid: String!
  inventoryclientid: String!
  quantity:Int!
  sellprice: Float!
  ticketItemID: String!}

 type TicketItem @model {
      id:ID!
      name: String!
      buyprice: Float!
      genericnfo: String!
      }

type SyncedMutations @model {
    id:ID!
    clientid: String!
    ownerclientid: String!
    tablename: String!
    itemid: String!
    mutation: String!
    from: String!
    completed: [String]
    itemdata: String!
}

然后:amplify codegen models

我还必须在启动时使用selectiveSync,如下所示:

代码语言:javascript
运行
复制
    AmplifyDataStore amplifyDataStore = AmplifyDataStore(modelProvider: 
    ModelProvider.instance, syncExpressions: [    
    DataStoreSyncExpression(SyncedMutations.classType, () => SyncedMutations.OWNERCLIENTID.eq(curClient))     
    DataStoreSyncExpression(Inventory.classType, () => Inventory.CLIENTID.eq(curClient)),
    ]);
    
      Amplify.addPlugin(amplifyDataStore);

然后,我在启动时设置一个服务,以订阅和侦听发生在SyncedMutations表上的事件,并在任何创建操作中更新本地inventory表。代码如下(需要清理):

代码语言:javascript
运行
复制
import ...

@LazySingleton()
class SyncMutationsService {
  static final SyncMutationsService _instance = SyncMutationsService._internal();
  final _clientService = locator<ClientService>();

  SyncMutationsService._internal() {
    Stream<SubscriptionEvent<SyncedMutations>> stream = Amplify.DataStore.observe(SyncedMutations.classType)
      ..listen(handleSubscription);
  }

  factory SyncMutationsService() => _instance;

  handleSubscription(SubscriptionEvent<SyncedMutations> event) async {
 if (event.eventType == EventType.create) {
    updateLocalProtectedTable(event.item);
    }
  }

  void updateLocalProtectedTable(SyncedMutations eventitem) {
    switch (eventitem.tablename) {
      case 'Inventory':
        print('Inventory table update.. ');
        updateInventoryOnEvent(eventitem);
        break;
    }
  }

  void updateInventoryOnEvent(SyncedMutations eventitem) {
    try {
      Inventory inventorydata = Inventory.fromJson(json.decode(eventitem.itemdata));

      SharedPreferencesHelper.getCurrentClientID().then((curClientID) {
        if (eventitem.completed == null || !eventitem.completed!.contains(curClientID)) {
          try {
            if (int.tryParse(eventitem.mutation) != null) {
              getCorrespondingInventoryLine(inventorydata.inventoryTicketItemID).then((oldLocalInvItem) {
                Inventory updatedInventoryItem = oldInvItem.copyWith(
                  quantity: oldLocalInvItem.quantity + int.parse(eventitem.mutation),
                );

                Amplify.DataStore.save(updatedInventoryItem).then((value) {
                  //update syncMutationLine completed client list
                  List<String> completedList = eventitem.completed ?? [];
                  completedList.add(_clientService.client.id);
                  Amplify.DataStore.save(eventitem.copyWith(completed: completedList));
                });
              });
            }
          } catch (e) {
            print('TicketItem was saved, but could not initialise stock into Inventory. ERROR: $e');
          }
        }
      });
    } catch (e) {
      print('Could not transpose inventory line data from syncMutation. ERROR: $e');
    }
  }


  Future<Inventory> getCorrespondingInventoryLine(String ticketItemID) async {
      double markup = await SharedPreferencesHelper.getBaseMarkup();

    return Amplify.DataStore.query(Inventory.classType).then((inventoryList) {
      return Amplify.DataStore.query(TicketItem.classType).then((ticketItemList) {
        TicketItem ti = ticketItemList.firstWhere((tItem) => tItem.id == ticketItemID);
        if (inventoryList.isNotEmpty) {
          return inventoryList.firstWhere((inventoryLine) => inventoryLine.inventoryTicketItemID == ticketItemID,
              orElse: () {
                return Inventory(
                    clientid: _clientService.client.id,
                    inventoryclientid: _clientService.client.id,
                    quantity: 0,
                    sellprice: markup * ti.buyprice,
                    inventoryTicketItemID: ticketItemID);
              });
        } else {
          return Inventory(
              clientid: _clientService.client.id,
              inventoryclientid: _clientService.client.id,
              quantity: 0,
              sellprice: markup * ti.buyprice,
              inventoryTicketItemID: ticketItemID);
        }
      });
    });
  }
}

现在,每当我想调整库存数量(或使用相同逻辑的任何其他表)时,我在本地直接保存到inventory,然后添加一个带有当前设备的clientID的syncedMutations条目,该条目将被派生给所有更改相同信息的其他客户端。就像这样:

代码语言:javascript
运行
复制
    Inventory updatedInventoryItem = oldInventoryItem.copyWith( 
   quantity:oldInventoryItem.quantity+valueOfMutation);
    
     
                  int mutationInt = valueOfMutation; // add 10, minus 4 etc
    
                  Amplify.DataStore.save(updatedInventoryItem).then((value) {
                    Amplify.DataStore.save(SyncedMutations(
                        clientid: clientService.client.id,
                        ownerclientid: clientService.actingClient.id,
                        completed: [clientService.client.id],
                        tablename: 'Inventory',
                        itemid: oldInventoryItem.ticketItemID,
                        mutation: mutationInt.toString(),
                        from: oldInventoryItem.quantity.toString(),
                        itemdata: json.encode(updatedInventoryItem.toJson())));
                  });

因此,假设我有两个客户端,它们都有间歇性的网络,而且不一定同时运行,当更新发生时,每个设备都会更改自己的库存,然后在网络连接时,将每个突变操作发送到云中,以找到具有相同clientID的任何其他设备,然后syncMutations会侦听create事件,并对其本地(但在线备份)版本的库存进行自己的更新。然后,它还将自己的clientID添加到最新的客户端列表中。

稍后,您可以运行一个测试,以摆脱所有syncedMutations,这些syncedMutations中的每个客户端都在完整的列表中。

我确信有一个更好或更健壮的方法来解决这个问题,但是它可以像预期的那样工作,同时将所有的逻辑都保存在设备上。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70384827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档